是否有一种干净、简单的方法可以使用 gtest 来模拟 C++ 中的非虚拟方法?尽管使用GoogleMock方式迫使你重新声明你的模拟类。
在我看来,这个功能对于在 C++ 中充分发挥 BDD、TDD 和模拟的潜力至关重要。我目前正在使用 FakeIt 但我仍然遇到这些困难 :
编辑: 我发现 Injector++ 和 isolate++ 这似乎是很好的解决方案,但不是跨平台的。
模拟非虚拟类从一开始就对我来说很痛苦,我想模拟一个类(虚拟和非虚拟方法)而不触及生产代码,因此不需要为每个类模板化或创建接口。
这就是你可以做到的。
诀窍是用模拟类替换感兴趣的类。 那么该怎么做呢?
假设您有一个名为
Production
的生产类,并且您想要测试该类,但它依赖于另一个名为 Dependency
的类,该类没有接口或虚拟方法。您需要模拟它才能测试 Production
类。
在 Production.h 中,所有包含语句注入以下代码后
#if TESTENV
#include "DependencyMock.h"
#define Dependency DependencyMock
#endif
因此,如果
TESTENV
已定义并处于活动状态,您将包含该类的模拟版本,并将文件中 Dependency
类的所有用法替换为 DependencyMock
类。
DependencyMock.h 可能看起来像这样:
#pragma once
#include "Dependency.h"
class DependencyMock
{
public:
void nonVirtualMethodToMock() {...};
int methodToWrap() { return dep_.methodToWrap(); }
private:
Dependency dep_;
};
您可以模拟任何和所有方法,但只包装您可以使用的方法可能会更容易、更好。
对生产代码 .h 文件的侵入也最小,我们并没有真正更改生产代码,我们只是在测试时更改它。
因此,在我看来,唯一的缺点是,要使其工作,您需要重新编译要模拟的类才能运行测试。
这是 CmakeLists.txt 示例:
add_executable(testProduction
testProduction.cpp
Production.cpp
DependencyMock.cpp
)
target_link_libraries(testProduction PRIVATE
${PRODUCTION_DEPEND_LIBS}
gtest_main
)
target_compile_definitions(testPoduction PRIVATE -DTESTENV=ON)
你就可以走了。
我不知道这是如何扩展的,因为我没有编写那么多测试,但现在它对我来说已经足够了,并且是迄今为止我所见过的最简单的方法(我没有使用任何平台,如 Isolator 或 Injector) 。 所以希望这有帮助:)