Мне нужно написать gtest для тестирования некоторого существующего кода, который имеет не виртуальный метод, поэтому я тестирую с использованием приведенного ниже источника, но я получаю ошибку компиляции
package / web / webscr / sample_template_class3.cpp: в функции — main () -:
package / web / webscr / sample_template_class3.cpp: 64: ошибка: у класса Templatemyclassâ нет члена с именем âgmock_displayâ
sample_template_class3.cpp
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace std;
template < class myclass>
class Templatemyclass
{
private:
myclass T;
public :
void display()
{
T.display();
}
};
class Test
{
public:
void display()
{
cout<<"Inside the display Test:" <<endl;
}
};
class MockTest
{
public:
MOCK_METHOD0(display,void());
};
class FinalTest
{
public:
void show( Templatemyclass<Test> t)
{
t.display();
cout<<"Inside the display FinalTest:" <<endl;
}};
int main()
{FinalTest test1;
Templatemyclass<Test> obj1;
Templatemyclass<MockTest> obj2;
EXPECT_CALL(obj2,display()).Times(1);
test1.show(obj1);
return 1;
}
В вашем коде есть несколько проблем. Я изменил его ниже и прокомментировал код для пояснения. Если это не достаточно ясно, добавьте комментарий, и я постараюсь объяснить дальше.
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace std;
template <class myclass>
class Templatemyclass {
private:
// Hold a non-const ref or pointer to 'myclass' so that the actual
// object passed in the c'tor is used in 'display()'. If a copy is
// used instead, the mock expectations will not be met.
myclass* T;
public :
// Pass 'myclass' in the c'tor by non-const ref or pointer.
explicit Templatemyclass(myclass* t) : T(t) {}
void display() { T->display(); }
};
class Test {
public:
void display() { cout << "Inside the display Test:" << endl; }
};
class MockTest {
public:
MOCK_METHOD0(display, void());
};
class FinalTest {
public:
// Templatise this function so we can pass either a Templatemyclass<Test>
// or a Templatemyclass<MockTest>. Pass using non-const ref or pointer
// again so that the actual instance with the mock expectations set on it
// will be used, and not a copy of that object.
template<class T>
void show(T& t) {
t.display();
cout<<"Inside the display FinalTest:" <<endl;
}
};
int main() {
Test test;
Templatemyclass<Test> obj1(&test);
MockTest mock_test;
Templatemyclass<MockTest> obj2(&mock_test);
EXPECT_CALL(mock_test,display()).Times(1);
FinalTest test1;
test1.show(obj1);
test1.show(obj2);
return 0;
}
Следующее могло бы упростить случай:
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
template <class myclass>
class Templatemyclass {
public:
myclass T;
void show() const { T.display(); }
};
struct Test {
void display() const { std::cout << "Inside the display Test:\n"; }
};
struct MockTest {
MOCK_CONST_METHOD0(display, void());
};
int main() {
Templatemyclass<Test> obj1;
obj1.show();
Templatemyclass<MockTest> obj2;
EXPECT_CALL(obj2.T, display()).Times(1);
obj2.show();
return 0;
}
Если вы не хотите менять свой исходный код, вы можете использовать инжектор ++.
В настоящее время он поддерживает только x86 Windows. Но поддержка Linux и x64 Windows скоро появится. Приведенные ниже примеры дадут вам краткое представление:
Ложные не виртуальные методы
Ниже пример подделок BaseClassTest::getAnInteger()
используя fakeFunc()
:
class FakeClassNonVirtualMethodTestFixture : public ::testing::Test
{
public:
int fakeFunc()
{
return 6;
}
};
TEST_F(FakeClassNonVirtualMethodTestFixture, FakeIntFunctionWhenCalled)
{
// Prepare
int expected = 6;
InjectorPP::Injector injector;
injector.whenCalled(INJECTORPP_MEMBER_FUNCTION(BaseClassTest::getAnInteger))
.willExecute(INJECTORPP_MEMBER_FUNCTION(FakeClassNonVirtualMethodTestFixture::fakeFunc));
BaseClassTest b = BaseClassTest();
// Act
// FakeFunc will be executed!
int actual = b.getAnInteger();
// Assert
EXPECT_EQ(expected, actual);
}
Поддельные виртуальные методы
Injector ++ поддерживает виртуальные методы насмешек (Удивительно, да?). Ниже приведен простой пример:
int FakeIntFuncForDerived()
{
return 2;
}
TEST_F(FakeClassVirtualMethodTestFixture, MockDerivedClassVirtualMemberFunctionWhenCalled)
{
// Prepare
int expected = 2;
BaseClassTest* derived = new SubClassTest();
InjectorPP::Injector injector;
injector.whenCalledVirtualMethod(derived, "getAnIntegerVirtual")
.willExecute(fakeIntFuncForDerived);
// Act
// FakeIntFuncForDerived() will be exectued!
int actual = derived->getAnIntegerVirtual();
// Assert
EXPECT_EQ(expected, actual);
delete derived;
derived = NULL;
}
Ложные статические методы
Injector ++ поддерживает статический метод пересмешивания. Ниже приведен простой пример:
Address FakeGetAnAddress()
{
Address addr;
addr.setAddressLine("fakeAddressLine");
addr.setZipCode("fakeZipCode");
return addr;
}
TEST_F(FakeClassNonVirtualMethodTestFixture, FakeStaticFunctionReturnUserDefinedClassWhenCalled)
{
// Prepare
Address expected;
expected.setAddressLine("fakeAddressLine");
expected.setZipCode("fakeZipCode");
InjectorPP::Injector injector;
injector.whenCalled(INJECTORPP_STATIC_MEMBER_FUNCTION(BaseClassTest::getAnAddressStatic))
.willExecute(INJECTORPP_MEMBER_FUNCTION(FakeClassNonVirtualMethodTestFixture::fakeGetAnAddress));
// Act
// FakeGetAnAddress will be executed!
Address actual = BaseClassTest::getAnAddressStatic();
// Assert
EXPECT_EQ(expected, actual);
}