单元测试:如何打破本地对象依赖?
我有如下代码:
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。
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 change 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不。没有任何解决方案不包括更改该设计,主要是因为该设计糟糕。 A 及其依赖项 B 紧密耦合,这使得面向对象编程变得非常糟糕:您需要反转依赖项的控制。测试只是该设计不好的原因之一,但并不是唯一的原因。可移植性、灵活性、关注点分离是其他因素。
使其可测试并使其变得更好的最佳方法(唯一的好方法)是依赖注入。
您需要使用构造函数(将 B 的接口作为参数)或 setter 将 B 注入 A 中。无论谁控制 A(并执行
new A()
),都应该将依赖项 B 传递给它(new A(new B())
,或A. setB(新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())
, orA.setB(new B())
).Once that is done, unit-testing the method will become very easy.
如果不进行更改,您就无法做到这一点,但您可以执行以下操作:
至少在 C# 中,我认为您正在编写此内容。没有处理太多指针,所以我不确定我的语法是否正确,但基本上的想法是对 pB 进行延迟初始化,以允许您注入依赖项(如果您愿意)但不会破坏当前行为。您可以更花哨一点,将
A
的备用构造函数设置为内部,然后使用InternalsVisibleTo
属性仅将其显示给您的测试类。You can't do this without making a change, but you could do something like:
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 theInternalsVisibleTo
attribute to only show it to your test classes.