gmock 如何mock一个模板类单例
下面是一个简单的办法:
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using ::testing::Return;
using ::testing::_;
template<typename T>
class mockFoo{
public:
static mockFoo& GetInstance(){
static mockFoo instance;
return instance;
}
MOCK_METHOD(T, bar, (const T&), ());
protected:
mockFoo() = default;
~mockFoo() = default;
mockFoo(const mockFoo&) = delete;
mockFoo& operator=(const mockFoo&) = delete;
};
class fooTest : public ::testing::Test {
protected:
void SetUp() override {
}
void TearDown() override {
}
};
TEST_F(fooTest, fooTest1){
auto& ins = mockFoo<int>::GetInstance();
EXPECT_CALL(ins, bar(_)).WillOnce(Return(42));
EXPECT_EQ(ins.bar(1), 42);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
红帽系安装gtest:
sudo dnf install gtest gtest-devel gmock-devel
编译:
g++ -std=c++17 main.cpp -lgtest -lgmock -lpthread -o test
当然,实际情况是,单例里面本身没有mock method,那我们就得创建一个子类来实现,并且新增SetInstance来替换掉单例。
使用裸指针报了很多内存问题,所以我改为使用智能指针。
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using ::testing::_;
using ::testing::Return;
template <typename T>
class Foo
{
private:
static std::unique_ptr<Foo> instance; // 不使用裸指针,防止内存问题
public:
static Foo &GetInstance()
{
if (!instance)
{
instance = std::make_unique<Foo>();
}
return *instance;
}
static void SetInstance(std::unique_ptr<Foo> newInstance)
{
instance = std::move(newInstance);
}
virtual T bar(const T &key) // 不能为纯虚函数
{
return key;
}
Foo() = default; // 构造和析构函数都要是 Public
virtual ~Foo() = default; // 不加virtual会报 leaked mock
Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;
};
template <typename T>
std::unique_ptr<Foo<T>> Foo<T>::instance = nullptr;
template <typename T>
class MockFoo : public Foo<T>
{
public:
MOCK_METHOD(T, bar, (const T &), (override));
};
class fooTest : public ::testing::Test
{
protected:
void SetUp() override
{
}
void TearDown() override
{
}
};
TEST_F(fooTest, fooTest1)
{
std::unique_ptr<MockFoo<int>> pt = std::make_unique<MockFoo<int>>();
EXPECT_CALL(*pt, bar(_)).WillOnce(Return(42)); // 不能放下一行的后面,所有权已经移走了
Foo<int>::SetInstance(std::move(pt));
EXPECT_EQ(Foo<int>::GetInstance().bar(1), 42);
}
TEST_F(fooTest, fooTest2)
{
std::unique_ptr<MockFoo<int>> pt = std::make_unique<MockFoo<int>>();
EXPECT_CALL(*pt, bar(_)).WillOnce(Return(43));
Foo<int>::SetInstance(std::move(pt));
EXPECT_EQ(Foo<int>::GetInstance().bar(2), 43);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
如果智能指针还是不过,那就用裸指针吧:
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using ::testing::_;
using ::testing::Return;
template <typename T>
class Foo
{
private:
static Foo* instance;
public:
static Foo &GetInstance()
{
if (!instance)
{
instance = new Foo();
}
return *instance;
}
static void SetInstance(Foo* newInstance)
{
delete instance;
instance = newInstance;
}
static void Release()
{
instance = nullptr;
}
virtual T bar(const T &key) // 不能为纯虚函数
{
return key;
}
Foo() = default; // 构造和析构函数都要是 Public
virtual ~Foo() = default; // 不加virtual会报 leaked mock
Foo(const Foo &) = delete;
Foo &operator=(const Foo &) = delete;
};
template <typename T>
Foo<T>* Foo<T>::instance = nullptr;
template <typename T>
class MockFoo : public Foo<T>
{
public:
MOCK_METHOD(T, bar, (const T &), (override));
};
class fooTest : public ::testing::Test
{
protected:
void SetUp() override
{
pt = new MockFoo<int>();
MockFoo<int>::SetInstance(pt);
}
void TearDown() override
{
MockFoo<int>::Release();
delete pt;
}
MockFoo *pt = nullptr;
};
TEST_F(fooTest, fooTest1)
{
EXPECT_CALL(*pt, bar(_)).WillOnce(Return(42));
EXPECT_EQ(Foo<int>::GetInstance().bar(1), 42);
}
TEST_F(fooTest, fooTest2)
{
EXPECT_CALL(*pt, bar(_)).WillOnce(Return(43));
EXPECT_EQ(Foo<int>::GetInstance().bar(2), 43);
}
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
本文来自博客园,作者:mariocanfly,转载请注明原文链接:https://www.cnblogs.com/mariocanfly/p/19394629

浙公网安备 33010602011771号