我在使用C++中的googlemock和依赖注入进行单元测试时遇到了困难。Mock和依赖注入可以显著地简化代码测试,但它们严重依赖于虚方法。虽然其他语言中的类默认使用虚方法,但C++不是这种情况。我正在使用C++创建一个低开销的性能测量框架,因此使每个类都继承自一个接口(带有纯虚方法)并不是一个理想的选择。
具体来说,我在测试包含对象集合的类时遇到了问题,例如以下内容:
为了测试这个类,我可以执行以下操作:
但是这样做不起作用,因为我无法为模拟对象设置期望,并且来自googlemock的模拟对象不可复制(因此,调用
为了解决这个问题,在测试时我可以使用指针代替(例如,
然后,我可以使用类型特征创建一个方法,如果给定一个引用,它只返回该引用,如果给定一个指针,则对指针进行解引用(例如,
因此,我想知道是否有更好的解决方案,或者是模拟和依赖注入不太适合C ++技术。
具体来说,我在测试包含对象集合的类时遇到了问题,例如以下内容:
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_;
// ...
};
为了测试这个类,我可以执行以下操作:
class mock_event {
public:
MOCK_METHOD0(read, void());
};
TEST(event_manager, test) {
event_manager<mock_event> manager;
// ...
}
但是这样做不起作用,因为我无法为模拟对象设置期望,并且来自googlemock的模拟对象不可复制(因此,调用
std :: transform
无法编译通过)。为了解决这个问题,在测试时我可以使用指针代替(例如,
event_manager<mock_event*>
),并将工厂传递给event_manager
构造函数。但是,由于诸如e.read()
之类的调用(在测试时应该改为e->read()
),所以这不会编译通过。然后,我可以使用类型特征创建一个方法,如果给定一个引用,它只返回该引用,如果给定一个指针,则对指针进行解引用(例如,
dereference(e).read()
)。但是,这只会增加大量复杂性,而且看起来不是一个好的解决方案(特别是如果需要对包含对象集合的所有类进行测试)。因此,我想知道是否有更好的解决方案,或者是模拟和依赖注入不太适合C ++技术。
event_manager
进行一些修改,使用std::vector<std::unique_ptr<Event>>
,也许这样可以解决问题。但我没有尝试过,所以不确定是否有效。 - Mineunique_ptr
和工厂(或更改接口以允许用户添加unique_ptr<Event>
)应该可以解决问题。但是我需要在生产中存储指针(而不仅仅是测试期间),我正在寻找避免这种情况的解决方案。 - betabandidounique_ptr
)。这应该不是问题。 - Mine