构建一个可以测试的类

时间:2012-03-27 08:32:35

标签: c# unit-testing

我有一个使用内部代理类来调用提供数据的服务的类。当然,如果该方法在内部创建代理,则测试该类存在问题。你认为代理应该在构造函数中给出,即使它可以在没有“知道”的情况下在里面创建吗?

3 个答案:

答案 0 :(得分:1)

您应该通过依赖注入(构造函数,属性,参数)为类提供类依赖性。这使您的类可测试并允许模拟所有这些依赖项。

更新: 注入服务代理:

class Foo
{
   private IServiceProxy _serviceProxy;
   public Foo(IServiceProxy _serviceProxy)
   {
        _serviceProxy = serviceProxy;
   }

   public void Bar()
   {
       var staff = _serviceProxy.GetStaff();
   }
} 

顺便说一句,请考虑隐藏有关您班级代理的信息。例如。通过代理实现与实际服务相同的接口,并为您的类提供IService。

UPDATE2(网关):

我们所有的域名需求 - 获得一些员工。所以,我们定义接口:

interface IStaffService
{
  Staff GetStaff();
}

我们的域类(您的测试类仅使用此接口,不依赖于Web服务,代理创建和其他基础结构问题)。

接下来为您的服务创建网关(请参阅Martin Fowler网站上的定义):

public MyServiceProxyGateway : IStaffService
{
    public Staff GetStaff()
    {
       var proxy = new YourProxyType();
       proxy.X = value;
       proxy.Y = value;
       var response = proxy.CallActualServiceMethod();
       Staff staff = new Staff();
       staff.Value = response.Something;
       return staff;
    }
} 

您的代码现在完全没有意识到所有这些基础架构通信。并且您使用方便的界面GetStaff而不是CallActualServiceMethod。

答案 1 :(得分:1)

嗯,“代理类知道如何实例化自己”和“类知道如何实例化代理类”之间存在差异。如果你把这些知识打包在内,那么第二个使单元测试变得更难(如果不是不可能的话)。

我使用依赖注入(通过框架,构造函数或属性)将这些知识带给调用者 - 并使其可测试。

答案 2 :(得分:1)

为了测试我的代理类,我通常会给出应该在构造函数中代理的目标。 Thous让我有可能给出一个存根对象进行测试。

public class MyProxy : IProxiedInterface
{
    private IProxiedInterface _Target;

    public MyProxy(IProxiedInterface target)
    {
        if(target == null)
            throw new ArgumentNullException("target");

        _Target = target;
    }

    // ToDo: Implement all functions from IProxiedInterface
    //       and delegate them to the target
    public bool DoSomething()
    {
        return _Target.DoSomething();
    }
}