gmock - 模拟派生类的非虚拟方法
gmock - mocking non-virtual method of the derived class
我正在使用VS2005和gmock ver. 1.6进行单元测试。
我有以下代码,我想模拟,但我找不到这样做的方法。
class A
{
virtual bool foo1() = 0;
virtual bool foo2() = 0;
};
class B : public A
{
virutal bool foo1();
virtual bool foo2();
static B* getInstance(int x);
static B* getInstance();
}
其中getInstance(int x)
只是创建 B 的实例并返回它。而getInstance()
只返回已创建的实例 getInstance(int x)
;
我有模拟课,
class MockA : public A
{
MOCK_METHOD0(foo1, bool());
MOCK_METHOD0(foo2, bool());
}
在源中,我正在使用
bool retVal = B::getInstance()->foo2()
我怎样才能B::getInstance()
模拟这种行为?
我认为你必须使用链接器接缝来做你想做的事。
假设我们已经libraryToBeMocked
了放置在libraryToBeMocked.hpp
中的接口:
#pragma once
class Base
{
public:
virtual bool evenCheck() = 0;
virtual bool oddCheck() = 0;
};
class Derived : public Base
{
public:
virtual bool evenCheck();
virtual bool oddCheck();
static Base* getInstance(int x);
static Base* getInstance();
private:
Derived(int x);
int x;
};
你应该已经注意到我已经改变了你的设计。getInstance
方法都返回指向Base
而不是Derived
的指针。如果你想清楚地模拟逻辑,你应该模拟纯接口 Derived 已经有一些逻辑了。恕我直言,无论如何getInstance
方法都应该移动到其他类。
该库的实现正在libraryToBeMockedImpl.cpp
#include "libraryToBeMocked.hpp"
#include <memory>
#include <cstdlib>
bool Derived::evenCheck() { return x % 2 == 0; }
bool Derived::oddCheck() { return x % 2 != 0; }
namespace
{
std::auto_ptr<Derived> current(NULL);
}
Base* Derived::getInstance(int x)
{
current.reset(new Derived(x));
return current.get();
}
Base* Derived::getInstance()
{
return current.get();
}
Derived::Derived(int x) : x(x) {}
还有您想要测试的逻辑。 testedLibrary.hpp
:
#pragma once
bool isOdd(int x);
bool isEven(int x);
实施testedLibraryImpl.cpp
:
#include "testedLibrary.hpp"
#include "libraryToBeMocked.hpp"
bool isOdd(int x)
{
return Derived::getInstance(x)->oddCheck();
}
bool isEven(int x)
{
return Derived::getInstance(x)->evenCheck();
}
main.cpp
中的虚拟main
:
#include <iostream>
#include "testedLibrary.hpp"
using namespace std;
int main()
{
int x;
cin >> x;
cout << x << " is odd:" << boolalpha << isOdd(x) << endl;
cout << x << " is even:" << boolalpha << isEven(x) << endl;
return 0;
}
我不使用 VS,但我认为只需要为项目添加main.cpp
testedLibraryImpl.cpp
和libraryToBeMockedImpl.cpp
。我宁愿使用 gcc:
g++ main.cpp libraryToBeMockedImpl.cpp testedLibraryImpl.cpp -o production
好吧,让我们从我的答案开始。我会创建头文件'libraryMockSeam.hpp':
#pragma once
#include "libraryToBeMocked.hpp"
class Provider
{
public:
virtual Base* getInstance() = 0;
virtual Base* getInstance(int x) = 0;
};
Provider* registerNewMockProvider(Provider*);
和libraryMockSeam.cpp
:
#include "libraryMockSeam.hpp"
namespace
{
Provider* currentProvider = 0;
}
Provider* registerNewMockProvider(Provider* newProvider)
{
Provider* t = currentProvider;
currentProvider = newProvider;
return t;
}
Base* Derived::getInstance()
{
return currentProvider->getInstance();
}
Base* Derived::getInstance(int x)
{
return currentProvider->getInstance(x);
}
如您所见,此源文件提供了它自己的getInstance
方法实现。它将其委托给注册的提供程序。标头引入了提供程序接口和允许注册提供程序的函数。就是这样。
让我们看一下测试:
#include "testedLibrary.hpp"
#include "libraryMockSeam.hpp"
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace ::testing;
class MockProvider : public Provider
{
public:
MOCK_METHOD1(getInstance, Base*(int x));
MOCK_METHOD0(getInstance, Base*());
};
class MyMock : public Base
{
public:
MOCK_METHOD0(evenCheck, bool());
MOCK_METHOD0(oddCheck, bool());
};
class MyTestSuite : public Test
{
public:
MyTestSuite()
{
registerNewMockProvider(&provider);
}
StrictMock<MyMock> mock;
StrictMock<MockProvider> provider;
};
TEST_F(MyTestSuite, checksForOddValue)
{
EXPECT_CALL(provider, getInstance(1)).Times(2).WillRepeatedly(Return(&mock));
EXPECT_CALL(mock, evenCheck()).WillOnce(Return(false));
EXPECT_CALL(mock, oddCheck()).WillOnce(Return(true));
EXPECT_TRUE(isOdd(1));
EXPECT_FALSE(isEven(1));
}
TEST_F(MyTestSuite, checksForEvenValue)
{
EXPECT_CALL(provider, getInstance(1)).Times(2).WillRepeatedly(Return(&mock));
EXPECT_CALL(mock, evenCheck()).WillOnce(Return(true));
EXPECT_CALL(mock, oddCheck()).WillOnce(Return(false));
EXPECT_TRUE(isEven(1));
EXPECT_FALSE(isOdd(1));
}
我会这样编译它:
g++ test.cpp testedLibraryImpl.cpp libraryMockSeam.cpp -lgmock -lgmock_main -lpthread -o test
您应该注意到,在这种情况下,我没有提供libraryToBeMocked.cpp
,libraryMockSeam.cpp
已经提供了实现。如果您想使用整个库(即*.lib
文件(或*.a
)),您将能够同时提供模拟库和接缝,但稍后应在库之前提供给链接器。
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- 是否可以使用基类非虚拟方法中的派生类虚拟方法?
- 如何编写 operator= 用于使用虚拟方法与非平凡成员的匿名联合
- 让编译器告诉什么确切的纯虚拟方法使结构抽象?
- 使用模板而不是虚拟方法的管道模式
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 为什么调用没有正文的纯虚拟方法不会导致链接器错误?
- 出于什么目的,非虚拟方法将与C++一起使用?
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 如何重写继承的嵌套类中存在的虚拟方法
- 私有虚拟方法有什么用?
- 基类可以声明虚拟方法但不定义它吗?仍然在派生类中定义
- googletest:测试基类具有纯虚拟方法的派生类时的核心转储
- 确保模拟的 GTest 方法覆盖虚拟方法
- CPP 继承虚拟方法解析顺序
- 我是否应该在包含虚拟方法的类上使用'memcpy'?如果没有,如何替换它?
- 用c++中的纯虚拟方法抽象模板类
- 解决虚拟方法的歧义继承的两种方法
- 没有针对完全专用模板类的外联虚拟方法定义