kir*_*kun 12 c++ unit-testing mocking googletest
假设我有课程
class Inner {
public:
void doSomething();
};
class Outer {
public:
Outer(Inner *inner); // Dependency injection.
void callInner();
};
Run Code Online (Sandbox Code Playgroud)
适当的单元测试说我应该进行测试Inner
.然后,我应该测试Outer
使用不是真实的Inner
,而是一个,MockInner
所以我将对添加的功能进行单元测试,Outer
而不是完整的堆栈Outer
/ Inner
.
要做到这一点,Googletest似乎建议Inner
变成一个纯粹的抽象类(接口),如下所示:
// Introduced merely for the sake of unit-testing.
struct InnerInterface {
void doSomething() = 0;
};
// Used in production.
class Inner : public InnerInterface {
public:
/* override */ void doSomething();
};
// Used in unit-tests.
class MockInner : public InnerInterface {
public:
/* override */ void doSomething();
};
class Outer {
public:
Outer(Inner *inner); // Dependency injection.
void callInner();
};
Run Code Online (Sandbox Code Playgroud)
所以,在生产代码中,我会使用Outer(new Inner)
; 在测试中,Outer(new MockInner)
.
好.理论上似乎很好,但是当我开始在整个代码中使用这个想法时,我发现自己为每个怪异的类创建了一个纯粹的抽象类.即使您可以忽略由于不必要的虚拟调度导致的轻微运行时性能降级,也会进行大量的锅炉板打字.
另一种方法是使用模板,如下所示:
class Inner {
public:
void doSomething();
};
class MockInner {
public:
void doSomething();
};
template<class I>
class Outer {
public:
Outer(I *inner);
void callInner();
};
// In production, use
Outer<Inner> obj;
// In test, use
Outer<MockInner> test_obj;
Run Code Online (Sandbox Code Playgroud)
这避免了电镀锅炉和不必要的虚拟调度; 但是现在我的整个代码库都处于惊人的头文件中,这使得无法隐藏源代码实现(更不用说处理令人沮丧的模板编译错误和长构建时间).
这两种方法,虚拟和模板,是进行适当单元测试的唯一方法吗?有没有更好的方法来进行适当的单元测试?
通过适当的单元测试,我的意思是每个单元测试只测试该单元引入的功能,但也不测试单元的依赖性.
我不认为你必须在实践中模拟测试类的每一个依赖.如果创建,使用或感知很复杂,那么是的.如果它直接依赖于某些不需要的外部资源,例如DB,网络或文件系统.
但如果这些都不是问题,IMO可以直接使用它的实例.由于您已对其进行了单元测试,因此您可以合理地确定它是按预期工作的,并且不会干扰更高级别的单元测试.
我个人更喜欢工作单元测试和简单,干净,可维护的设计,而不是坚持单元测试纯粹主义者的理想设置.
每个单元测试仅测试该单元引入的功能,但也不测试单元的依赖性.
使用功能和测试功能是两回事.
归档时间: |
|
查看次数: |
2044 次 |
最近记录: |