C+中的模拟和依赖注入+; 我努力在C++中进行单元测试和依赖注入。模拟和依赖注入大大简化了代码测试,但它们严重依赖于虚拟方法。虽然其他语言的类默认使用虚拟方法,但C++不是这样。我用C++来创建一个低开销的性能测量框架,所以让每个类从接口继承(W/纯虚方法)不是一个理想的选择。
具体来说,我在测试包含对象集合的类时遇到了问题,例如:C+中的模拟和依赖注入+; 我努力在C++中进行单元测试和依赖注入。模拟和依赖注入大大简化了代码测试,但它们严重依赖于虚拟方法。虽然其他语言的类默认使用虚拟方法,但C++不是这样。我用C++来创建一个低开销的性能测量框架,所以让每个类从接口继承(W/纯虚方法)不是一个理想的选择。,c++,unit-testing,dependency-injection,mocking,googlemock,C++,Unit Testing,Dependency Injection,Mocking,Googlemock,具体来说,我在测试包含对象集合的类时遇到了问题,例如: struct event_info { /* ... */ }; template<typename Event> class event_manager { public: event_manager(const std::vector<event_info>& events) { std::transform(begin(events), end(events), std::
struct event_info { /* ... */ };
template<typename Event>
class event_manager {
public:
event_manager(const std::vector<event_info>& events) {
std::transform(begin(events), end(events),
std::back_inserter(events_),
[](const event_info& info) { return Event{info}; });
}
void read() {
for (auto& e : events_)
e.read();
}
// ...
private:
std::vector<Event> events_;
// ...
};
struct event_info{/*…*/};
模板
类事件管理器{
公众:
事件管理器(const std::vector&events){
转换(开始(事件)、结束(事件),
标准::返回插入器(事件),
[](const event_info&info){return event{info};});
}
无效读取(){
用于(自动&e:事件)
e、 read();
}
// ...
私人:
向量事件;
// ...
};
要测试该类,我可以执行以下操作:
class mock_event {
public:
MOCK_METHOD0(read, void());
};
TEST(event_manager, test) {
event_manager<mock_event> manager;
// ...
}
类模拟事件{
公众:
模拟方法0(读取,void());
};
测试(事件管理器,测试){
活动经理;
// ...
}
但这不起作用,因为我无法设置mock对象的期望值,并且googlemock中的mock对象不可复制(因此,对std::transform
的调用无法编译)
为了解决这个问题,在测试时,我可以使用指针(例如,event\u manager
),并将工厂传递给event\u manager
构造函数。但是,由于调用了e.read()
(测试时应改为e->read()
),因此无法编译该文件
然后,我可以使用类型特征创建一个方法,如果给定一个引用,该方法只返回引用,如果给定一个指针,则取消对指针的引用(例如,dereference(e).read()
)。但是,这只会增加大量的复杂性,而且看起来不是一个好的解决方案(特别是当需要测试包含对象集合的所有类时)
所以我想知道是否有更好的解决办法,或者只是嘲讽和依赖注入不是C++的非常合适的技术。< P>我假定你在用一个简单的类模拟你的标准用例之前做出适当的性能测量,然后决定你的应用程序不能忍受指针引用去执行虚拟函数的开销。打电话 如果您阅读了gmock文档,它们会有一个“高性能模拟”部分,其中展示了如何在生产代码中使用模板来模拟非虚拟函数 我认为代码的第一条规则(生产或测试)是使代码尽可能简单,因此我不相信使用模板更改生产代码只是为了能够测试它(尽管另一方面,我完全赞成使用TDD作为生产代码设计的评论和指南) 因此,您的应用程序似乎需要另一个模拟框架,该框架允许在链接时而不是运行时执行模拟
检查CPPTEST和CPUMOKK(),这可以模拟C自由站立函数和C++非虚拟方法。
使用cpputest/cppumock的代价是它需要比gmock更多的样板文件,但它非常好。这是一个好问题!我希望得到答案。据我所知,也许你可以尝试修改一下
事件管理器
,使用std::vector
,也许这就解决了问题。但是我还没有尝试过,所以不确定它是否有效。@我的使用unique\u ptr
和一个工厂(或者只是更改界面以允许用户添加unique\u ptr
)应该有效。但是我也需要在生产中存储指针(不仅仅是在测试时),我正在寻找一种解决方案来避免这种情况。是的,我的意思是你可以在生产代码和测试代码中存储指针(unique_ptr
)。这应该不是问题。看起来您可以给出模拟副本语义,但您必须自己编写代码。这意味着您仍然可以使用模板依赖项注入。是的,对于一些短函数来说,它有很大的不同。我一定会看一看cpputest。