我有一个从基类继承的多派生类,如下所示,并希望模拟所有派生类。
我需要创建一个MockBase类吗?还是需要在每个派生类mock对象中重复基类方法?
注意:我想测试Dervied1User&Dervied2User,因此想要创建MockDervied1和MockDerived2。Dervied1User调用了Dervied1和基类中的方法。
class base {
base() { .. }
virtual ~base(..) { ... }
virtual bool method0(..) { ... }
virtual bool method1(..) { ... }
virtual void method2(..) { ... }
};
class Derived1 : public base {
Derived1() { ... }
virtual int method3(..) { ... }
virtual int method4(..) { ... }
};
class Derived2 : public base() {
Derived2() { ... }
virtual int method5(..) { ... }
virtual int method6(..) { ... }
};
class Derived3 : public base() {
Derived2() { ... }
virtual int method7(..) { ... }
virtual int method8(..) { ... }
};
class Dervied1User {
public:
Dervied1User(std::unique_ptr<Derived1> d1_) : d1(std::move(d1_)) {}
int method9(..) {...}
private:
std::unique_ptr<Derived1> d1;
};
class Dervied2User {
....
}
派生类的mock是这样的吗?在所有派生类mock中重复方法0、方法1和方法2。
class MockDerived1 : pubic Derived1 {
MOCK_METHOD(method0, ....)
MOCK_METHOD(method1, ....)
MOCK_METHOD(method2, ....)
MOCK_METHOD(method3, ....)
MOCK_METHOD(method4, ....)
}
class MockDerived2 : pubic Derived2 {
MOCK_METHOD(method0, ....)
MOCK_METHOD(method1, ....)
MOCK_METHOD(method2, ....)
MOCK_METHOD(method5, ....)
MOCK_METHOD(method6, ....)
}
选项1:什么都不做
如果在测试Derived1
的过程中不需要拦截对base
的调用,那么就不必做任何事情。有问题的方法都不是纯虚拟的,所以不嘲笑它们只会回退到基本实现。显然,这是否有可能是高度相关的。
class MockDerived1 : public Derived1 {
MOCK_METHOD(method3, ....)
MOCK_METHOD(method4, ....)
};
class MockDerived2 : public Derived2 {
MOCK_METHOD(method5, ....)
MOCK_METHOD(method6, ....)
};
N.B.选项1对您来说是一种代码气味。当你想模拟一个方法时,你可能会意外地这样做,编译器会让你这样做。如果创建一个base
继承的baseInterface
抽象基类是可能的,我会认真推荐它
选项2:在每个派生实体模型中重复基本实体模型
派生类的mock是这样的吗?在所有派生类mock中重复方法0、方法1和方法2。
class MockDerived1 : public Derived1 {
MOCK_METHOD(method0, ....)
MOCK_METHOD(method1, ....)
MOCK_METHOD(method2, ....)
MOCK_METHOD(method3, ....)
MOCK_METHOD(method4, ....)
};
class MockDerived2 : public Derived2 {
MOCK_METHOD(method0, ....)
MOCK_METHOD(method1, ....)
MOCK_METHOD(method2, ....)
MOCK_METHOD(method5, ....)
MOCK_METHOD(method6, ....)
};
是的,这很好用!不过,它可能很烦人,而且可能容易出错。如果您更改base
,则需要更新每个派生的mock类,这在某些代码库中可能是一件繁重的工作。
注意。选项1和2并不互斥,您可以选择需要模拟的方法,只要在测试期间在base
中执行实现是可以的。
选项3:使用宏
为了减少重复,可以做的一件相当简单的事情是创建一个宏,将base
的mock添加到任何给定的子类中。一个明显的优点是,如果base
发生更改,您只需更改宏,所有mock都将立即更新。Google mock已经是以宏观为中心的,所以这是一个它们并不完全不合时宜的案例:
#define MOCK_BASE_MEMBERS()
MOCK_METHOD(method0, ....)
MOCK_METHOD(method1, ....)
MOCK_METHOD(method2, ....)
// end of macro
class MockDerived1 : public Derived1 {
MOCK_BASE_MEMBERS()
MOCK_METHOD(method3, ....)
MOCK_METHOD(method4, ....)
};
class MockDerived2 : public Derived2 {
MOCK_BASE_MEMBERS()
MOCK_METHOD(method5, ....)
MOCK_METHOD(method6, ....)
};
#undef MOCK_BASE_MEMBERS
选项4:MockBase
既然你在问题中提到了它,那么让我们讨论一下MockBase
需要什么。
有几种不同的方法可以实现这一点,但只有一种是可行的。
由于您希望类层次结构看起来像CCD_ 10,这意味着CCD_ 11需要为每个Dervied类从不同的基继承。这是模板的工作:
template<typename T>
class MockBase : public T {
MOCK_METHOD(method0, ....)
MOCK_METHOD(method1, ....)
MOCK_METHOD(method2, ....)
};
class MockDerived1 : public MockBase<Derived1> {
MOCK_METHOD(method3, ....)
MOCK_METHOD(method4, ....)
};
如果你对宏完全过敏,你可能想这样做,但我个人觉得这比必要的更复杂。