GTest:模拟非虚拟成员函数
GTest: mocking non-virtual member function
考虑以下代码片段:
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()
函数。实际上,我不需要调用后一个函数,相反,我想 return,例如 3
。考虑到 get_ips()
是 非虚拟 函数,我该怎么做。如果可能的话,我不想更改源代码。我还阅读了以下文档https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md,但无法达到我想要的结果。
看来你可能遇到的问题是你试图模拟 class settings
,但是跟踪器的构造函数实际上没有办法 使用你的模拟设置class,因为它在编译时被固定为直接引用settings
。
食谱确实在“Mocking Nonvirtual Methods”下解释了如何解决这个问题:首先,你制作你的模拟 class,然后你提供一些 依赖注入的方法 允许您在编译时在 class 的生产版本和模拟版本之间 select。一种方法是使跟踪器成为一个 class 模板参数化设置 class 类似:
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>
。
可能没有办法在不更改代码的情况下解决这个问题。
考虑以下代码片段:
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()
函数。实际上,我不需要调用后一个函数,相反,我想 return,例如 3
。考虑到 get_ips()
是 非虚拟 函数,我该怎么做。如果可能的话,我不想更改源代码。我还阅读了以下文档https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md,但无法达到我想要的结果。
看来你可能遇到的问题是你试图模拟 class settings
,但是跟踪器的构造函数实际上没有办法 使用你的模拟设置class,因为它在编译时被固定为直接引用settings
。
食谱确实在“Mocking Nonvirtual Methods”下解释了如何解决这个问题:首先,你制作你的模拟 class,然后你提供一些 依赖注入的方法 允许您在编译时在 class 的生产版本和模拟版本之间 select。一种方法是使跟踪器成为一个 class 模板参数化设置 class 类似:
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>
。
可能没有办法在不更改代码的情况下解决这个问题。