能够模拟非虚拟方法和C函数的C++模拟框架
C++ mock framework capable of mocking non-virtual methods and C functions
我知道这个问题的第一部分以前被问过,但那是很久以前的事了:)。我想知道,在模拟非虚拟方法和C函数时,是否有任何开源模拟框架赶上了Typemock Isolator++。我最感兴趣的是Linux下的gcc。到目前为止,我对模拟访问者感兴趣(这样我就可以模拟模拟对象中的状态——见下文),并替换其他库中的C函数(select、pcap_*等)
class Foo {
public:
...
bool IsCondition() { return condition; };
...
private:
bool condition;
}
// I want a framework that allows me to do something like this:
TEST(TestFoo) {
MOCK_INTERFACE(Foo) mock_foo;
EXPECT_CALL(mock_foo, IsCondition).returns(true);
EXPECT(mock_foo.IsCondition());
}
GMock支持他们所说的用于模拟非虚拟方法的高性能依赖注入。
从上面的链接来看,要点是使用模板:
template <class PacketStream>
void CreateConnection(PacketStream* stream) { ... }
template <class PacketStream>
class PacketReader {
public:
void ReadPackets(PacketStream* stream, size_t packet_num);
};
然后,您可以在生产代码中使用CreateConnection()和PacketReader,并在测试中使用CreateConnection[()和PacketReader。
对于C函数,他们推荐接口,所以可能不是您想要的。但是,如果有单独的库,则可以始终链接到测试库,该测试库包含与部署库具有相同签名的函数。如果你觉得特别大胆,你甚至可以用LD_PRELOAD动态地完成它。这听起来和我有很多联系。
Cxxtest,如果你在高级功能的第8.1节中查看,它支持一些宏,使使用/创建界面更容易:
来自该链接:
CXXTEST_MOCK_GLOBAL( time_t, /* Return type */
time, /* Name of the function */
( time_t *t ), /* Prototype */
( t ) /* Argument list */ );
8.1.2. Mock Functions in Tested Code
测试的代码使用模拟全局函数,而不是直接使用全局函数。您可以访问T(for Test)命名空间中的mock函数,因此测试代码调用T::time()而不是time()。这相当于使用抽象接口而不是具体类。
// rand_example.cpp
#include <time_mock.h>
int generateRandomNumber()
{
return T::time( NULL ) * 3;
}
我过去在Cxxtest方法方面运气不错。
使用最近的GCC(例如4.6),您可以用C编写插件,或者用MELT编写扩展。
然而,要自定义GCC(通过C中的插件或MELT中的扩展),您需要部分了解其内部表示(Gimple和Tree-s),这需要时间(可能需要一周以上的工作)。因此,如果您有足够大的代码库,值得付出努力,那么这种方法是有意义的。
如果禁用内联并使用与位置无关的代码进行编译,ELFSpy支持替换(成员)函数。
你的测试可以写如下
// define alternate implementation for Foo::IsCondition
bool IsConditionTest(Foo*) { return true; }
int main(int argc, char** argv)
{
// initialise ELFSpy
spy::initialise(argc, argv);
// create a handle for intercepting Foo::IsCondition calls
auto method_spy = SPY(&Foo::IsCondition);
// relink original method to different implementation
auto method_fake = spy::fake(method_spy, &IsConditionTest);
// capture return value(s) from calls to Foo::IsCondition
auto returned = spy::result(method_spy);
// execute your test
Foo foo;
bool simulate = foo.IsCondition(); // calls IsConditionTest instead
// check it worked
assert(returned.value() == true);
}
上面的例子有效地在运行时重新链接代码,以调用IsConditionTest而不是Foo::IsCondition,这样您就可以用您想要的任何东西来替换它。函数/方法也可以用lambdas代替。
请参阅https://github.com/mollismerx/elfspy/wiki详细信息。免责声明:我写了ELFSpy。
- 模拟成员函数调用 lambda
- 如何使用类模拟 C++11 中的 lambda 函数和闭包?
- 如何反复调用函数直到满足模拟?
- 在类 gtest/gmock 进行单元测试时模拟成员函数C++
- EXPECT_CALL具有 unique_ptr 引用类型参数的模拟函数
- gmock - 如何使用 noexcept 说明符模拟函数
- 将模板函数声明为非模拟函数的参数
- C++如何在没有隐式转换的情况下模拟函数?
- 如何匹配通过引用传递给模拟函数的结构字段
- 使用GoogleMock调用聚合对象调用的模拟函数
- gtest-将模拟函数参数分配()
- 如何将 GMock EXPECT_CALL设置为为模拟函数调用两个不同的函数
- 使用Gmock将真实函数重新路由到模拟函数
- 从模拟函数调用中捕获 void* 参数
- 有没有办法使模拟函数与ON_CALL "interesting"?
- 如何验证传递给模拟函数的参数的派生类型
- 谷歌模拟函数改变参数值
- 将EXPECT_CALL()s和对模拟函数的调用交叉使用
- 对传递给模拟函数的参数调用成员函数的最简单方法是什么?
- 如何测试使用 MPI 调用的 CC++ 代码:是否有任何一组我可以使用的模拟函数