单元测试:如何打破本地对象依赖?

时间:2011-10-04 13:36:47

标签: unit-testing nunit unmanaged

我的代码如下:

class B;

class A
{
  A()
  {
  }
  bool MethodA()
  {
    B *pB = new B();
    bool bRet = pB->SomeFunction();
    // remaining logic;
    return bRet;
  }
  ~A(){}
};

我需要为 MethodA 编写测试。所以我认为我需要打破对 B 类的依赖。最好的方法是什么?如果它是一个成员变量,我可以通过构造函数注入一个存根。是否存在不涉及更改生产代码的解决方案? 如果需要改变,最好的方法是什么?

我使用NUnit并在这里处理一些非托管代码。请帮忙!

编辑:我错过了另一个头疼的问题! B类是一个C ++类,我不应该改变它的实现。 A类在C ++ / CLI中,它充当B的包装器。所以我认为这会抑制B接口的概率,因为我无法触及B.

2 个答案:

答案 0 :(得分:2)

没有。没有解决方案不包括改变设计,主要是因为该设计不好。 A和它的依赖关系B是紧密耦合的,这使得它在面向对象编程方面变得很糟糕:你需要反转依赖关系的控制。测试只是设计糟糕的一个原因,但它并不是唯一的原因。可移植性,灵活性,关注点分离等等。

使其可测试并使其更好的最佳方式(唯一的好方法)是依赖注入。 您需要使用构造函数(将B接口作为参数)或setter将B注入A中。控制A(并且new A())的任何人都应该将依赖关系B传递给它(new A(new B())A.setB(new B()))。

一旦完成,对方法进行单元测试将变得非常容易。

答案 1 :(得分:1)

如果不做出改变,你就无法做到这一点,但你可以这样做:

class A
{
  A()
  {
  }


  A(B *b)
  {
     pB = b;
  }

  B *pB;

  bool MethodA()
  {
    if (*pB == null) {
      *pB = new B();
    }
    bool bRet = pB->SomeFunction();
    // remaining logic;
    return bRet;
  }
  ~A(){}
};

至少在C#这是我认为你写的。没有处理很多指针,所以我不确定我的语法是否合适,但基本上我的想法是对pB进行延迟初始化,以便在你想要的时候注入依赖但不会破坏当前的行为。您可以获得更多的动力并为A internal制作备用构造函数,然后使用InternalsVisibleTo属性仅将其显示给您的测试类。