请考虑以下代码段:
source.hpp
class tracker
{
public:
static tracker& get_instance()
{
static tracker instance;
return instance;
}
tracker(const tracker&) = delete;
tracker& operator=(const tracker&) = delete;
private:
tracker()
{
_ip_count = settings::get_instance().get_ips();
// ...
}
private:
int _ip_count;
};
test.cpp
#include "source.hpp"
#include "settings.hpp"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
struct MockSettings
{
MOCK_CONST_METHOD0(get_ips, int());
};
TEST(tracker, _)
{
// Need to mock settings::get_instance().get_ips() function here
tracker& inst = tracker::get_instance();
}
int main(int argc, char** argv)
{
::testing::InitGoogleMock(&argc, argv);
return RUN_ALL_TESTS();
}
正如您在test.cpp
中看到的那样,我正在获取tracker
的实例,因此调用了settings::get_instance().get_ips()
函数。实际上,我不需要调用后一个函数,相反,我想返回例如3
。考虑到get_ips()
是非虚拟函数,我该怎么做。如果可能的话,我不想更改源代码。我也阅读了以下文档https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md,但无法达到我想要的结果。
答案 0 :(得分:1)
您似乎在这里遇到的问题是,您正在尝试模拟settings
类,但跟踪器的构造函数无法实际使用设置类,因为它在编译时固定为直接引用settings
。
该菜谱确实在“ Mocking Nonvirtual Methods”下说明了如何解决此问题:首先,创建您的模拟类,然后提供一些依赖注入方法,供您选择在编译时在类的生产版本和模拟版本之间切换。一种方法是使tracker成为一个由settings类参数化的类模板,例如:
template <typename settings_class> class tracker_template
{
public:
static tracker_template<settings_class>& get_instance()
{
static tracker_template<settings_class> instance;
return instance;
}
// ...
private:
tracker_template()
{
_ip_count = settings_class::get_instance().get_ips();
// ...
}
// ...
};
之后,您可以例如。 using tracker = tracker_template<settings>;
继续在生产代码中使用跟踪器,而在测试代码中使用tracker_template<MockSettings>
。
在不更改代码的情况下,可能没有办法解决这个问题。