开发者

Unit Testing: How to break a local object dependency?

开发者 https://www.devze.com 2023-04-11 04:24 出处:网络
I\'ve a code like following: class B; class A { A() { } bool MethodA() { B *pB = new B(); bool bRet = pB->SomeFunction();

I've a code like following:

class B;

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

I need to write tests for MethodA. So I think I need to break the dependency on class B. What is the best way to do it? If it was a member variable, I could have injected a stub via constructor. Is there any solution that doesn't involve change in production code? If a cha开发者_运维百科nge is necessary, what's the best way?

I use NUnit and is working on some unmanaged code here. Please help!

edit: There is another headache that I missed! class B is a C++ class which I shouldn't change its implementation. class A is in C++/CLI, which acts as wrapper to B. So I think that inhibits the probability of an Interface for B as I cannot touch B.


No. There is no solution that doesn't include changing that design, mostly because that design is bad. A and its dependency B are tightly coupled, which makes as bad as it gets in terms of object-oriented programming: you need to invert the control of dependencies. Testing is only one reason why that design is bad, but it's not the only one. Portability, flexibility, separation of concerns, are other.

The best way (the only good way) to make it testable, and to make it better, is dependency injection. You need to inject B into A, using either a constructor (that takes an interface to B as a parameter) or a setter. And whoever controls A (and does a new A()) should pass the dependency B to it (new A(new B()), or A.setB(new B())).

Once that is done, unit-testing the method will become very easy.


You can't do this without making a change, but you could do something like:

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(){}
};

At least in C# which is what I think you are writing. Haven't dealt much with pointers, so I'm not sure if I got the syntax right, but basically the idea is to do lazy initialization of pB to allow you to inject a dependency if you'd like but not break the current behavior. You could get a bit fancier and make the alternate constructor for A internal and then use the InternalsVisibleTo attribute to only show it to your test classes.

0

精彩评论

暂无评论...
验证码 换一张
取 消