为了模拟对象,我们是否应该将所有成员函数声明为虚拟(C++)?
In order to mock objects, shall we declare all member functions virtual(C++)?
虚函数在运行时有开销。但是如果没有虚函数,我们就不能模拟对象来做单元测试。
最佳做法是什么?
谢谢!
But without virtual function, we can not mock objects to do unit test.
这不完全正确。从 Google Mock Cookbook 开始,您实际上可以模拟非虚函数:
One way to do it is to templatize your code that needs to use a packet stream. More specifically, you will give your code a template type argument for the type of the packet stream. In production, you will instantiate your template with ConcretePacketStream as the type argument. In tests, you will instantiate the same template with MockPacketStream. For example, you may write:
template <class PacketStream>
void CreateConnection(PacketStream* stream) { ... }
template <class PacketStream>
class PacketReader {
public:
void ReadPackets(PacketStream* stream, size_t packet_num);
};
Then you can use CreateConnection<ConcretePacketStream>()
and PacketReader<ConcretePacketStream>
in production code, and use CreateConnection<MockPacketStream>()
and PacketReader<MockPacketStream>
in tests.
MockPacketStream mock_stream;
EXPECT_CALL(mock_stream, ...)...;
... set more expectations on mock_stream ...
PacketReader<MockPacketStream> reader(&mock_stream);
... exercise reader ...
虚函数在运行时有开销。但是如果没有虚函数,我们就不能模拟对象来做单元测试。
最佳做法是什么?
谢谢!
But without virtual function, we can not mock objects to do unit test.
这不完全正确。从 Google Mock Cookbook 开始,您实际上可以模拟非虚函数:
One way to do it is to templatize your code that needs to use a packet stream. More specifically, you will give your code a template type argument for the type of the packet stream. In production, you will instantiate your template with ConcretePacketStream as the type argument. In tests, you will instantiate the same template with MockPacketStream. For example, you may write:
template <class PacketStream> void CreateConnection(PacketStream* stream) { ... } template <class PacketStream> class PacketReader { public: void ReadPackets(PacketStream* stream, size_t packet_num); };
Then you can use
CreateConnection<ConcretePacketStream>()
andPacketReader<ConcretePacketStream>
in production code, and useCreateConnection<MockPacketStream>()
andPacketReader<MockPacketStream>
in tests.MockPacketStream mock_stream; EXPECT_CALL(mock_stream, ...)...; ... set more expectations on mock_stream ... PacketReader<MockPacketStream> reader(&mock_stream); ... exercise reader ...