Gmock 无法模拟在同一 class 中调用另一个方法的方法
Gmock can't mock a method that called in another method in the same class
我正在研究 Gmock(Google 测试框架)。
我 运行 遇到了一个问题,我认为 Gmock 可以解决它,但它不能。请查看:
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace std;
using ::testing::Invoke;
//---- THINGS TO TEST ---------
class MyTest {
public:
void display(const char* str);
void show_text();
};
void MyTest::display(const char* str){
cout << __func__<< " " << str << "\n";
cout << ":-->Inside the display myTest\n";
}
void MyTest::show_text(){
display("INSIDE MYTEST"); // HOW to mock display() here ?
}
//-------------------------------
//--- Configuration to test myTest ----
template <class myclass>
class Caller {
public:
myclass T;
void call_show_text() ;
void call_display(const char* s) ;
};
template <class myclass>
void Caller<myclass>::call_show_text()
{
T.show_text();
}
template <class myclass>
void Caller<myclass>::call_display(const char* str)
{
T.display(str);
}
void my_display(const char* str){
cout << __func__<< " OUTSIDE MYTEST\n" <<":-->Outside the display myTest\n";
}
struct MockTest {
MOCK_METHOD1(display, void(const char*));
MOCK_METHOD0(show_text, void());
};
//-------------------------------
//----- Test cases -------------
//----- Test cases -------------
TEST(TestShowTextMethod, CallDisplayOfmyTest){
Caller<MyTest> obj1;
obj1.call_show_text();
}
TEST(TestShowTextMethod, ReroutingDisplayToNewFunctionWithCallDisplay){
Caller<MockTest> obj2;
EXPECT_CALL(obj2.T, display("test_obj_2"))
.Times(1)
.WillOnce(Invoke(my_display));
obj2.call_display("test_obj_2");
}
TEST(TestShowTextMethod, ReroutingDisplayToNewFunctionWithCallShowText){
Caller<MockTest> obj3;
EXPECT_CALL(obj3.T, display("test_obj_3"))
.Times(1)
.WillOnce(Invoke(my_display));
obj3.call_display("test_obj_3");
}
TEST(TestShowTextMethod, ReroutingToNewFunctionWithCallShowText){
const char * str = "INSIDE MYTEST";
Caller<MockTest> obj4;
EXPECT_CALL(obj4.T, show_text());
EXPECT_CALL(obj4.T, display(str))
.Times(1)
.WillOnce(Invoke(my_display));
obj4.call_show_text();
}
//-------------------------------
//--- Initialization for test ----
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
只关注第四个测试,我认为 Gmock 可以处理第四个测试:show_text
调用 display
,为什么我不能在这种情况下模拟 display
? Gmock im是否可以模拟一个方法在同一个方法中调用另一个方法class or 我在第4个中犯了一定的错误测试用例 ?我得到了这样一个失败的测试结果:
../test_program.cpp:100: Failure
Actual function call count doesn't match EXPECT_CALL(obj4.T, display(str))...
Expected: to be called once
Actual: never called - unsatisfied and active
当然,show_text
和display()
是完全一样的调用。
有人有想法吗?
why I can't mock display
in this case?
您不仅成功地模拟了 display
,而且还模拟了 show_text
。你不应该依赖模拟实现的行为,因为它不会被调用。
Is Gmock impossible to mock a method is called in another method in the same class.
这是可能的,但远非完美,您可以在下面找到示例。请注意,仅针对测试进行了一些权衡。使 DisplayController::display 成为虚拟 class 可能是最大的一个。
class DisplayController
{
public:
virtual void display(const std::string& text)
{
cout << text << endl;
}
void show_str(const std::string& text)
{
cout << "Start" << endl;
display(text);
cout << "End" << endl;
}
};
class TestableDisplayController : public DisplayController
{
public:
MOCK_METHOD1(display, void(const std::string&));
MOCK_METHOD1(show_str_called, void(const std::string&));
void show_str(const std::string& text)
{
show_str_called(text);
DisplayController::show_str(text);
}
};
template <typename T>
class ClassUnderTest
{
public:
ClassUnderTest(T& display)
: displayController(display)
{}
void callDirectDisplay(const std::string& text)
{
displayController.display(text);
}
void callIndirectDisplay(const std::string& text)
{
displayController.show_str(text);
}
private:
T& displayController;
};
TEST(test, example)
{
TestableDisplayController mockedDisplayController;
ClassUnderTest<TestableDisplayController> sut(mockedDisplayController);
std::string l_directDisplay = "directDisplay";
std::string l_indirectDisplay = "indirectDisplay";
EXPECT_CALL(mockedDisplayController, display(l_directDisplay));
sut.callDirectDisplay(l_directDisplay);
EXPECT_CALL(mockedDisplayController, display(l_indirectDisplay));
EXPECT_CALL(mockedDisplayController, show_str_called(l_indirectDisplay));
sut.callIndirectDisplay(l_indirectDisplay);
}
我正在研究 Gmock(Google 测试框架)。 我 运行 遇到了一个问题,我认为 Gmock 可以解决它,但它不能。请查看:
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace std;
using ::testing::Invoke;
//---- THINGS TO TEST ---------
class MyTest {
public:
void display(const char* str);
void show_text();
};
void MyTest::display(const char* str){
cout << __func__<< " " << str << "\n";
cout << ":-->Inside the display myTest\n";
}
void MyTest::show_text(){
display("INSIDE MYTEST"); // HOW to mock display() here ?
}
//-------------------------------
//--- Configuration to test myTest ----
template <class myclass>
class Caller {
public:
myclass T;
void call_show_text() ;
void call_display(const char* s) ;
};
template <class myclass>
void Caller<myclass>::call_show_text()
{
T.show_text();
}
template <class myclass>
void Caller<myclass>::call_display(const char* str)
{
T.display(str);
}
void my_display(const char* str){
cout << __func__<< " OUTSIDE MYTEST\n" <<":-->Outside the display myTest\n";
}
struct MockTest {
MOCK_METHOD1(display, void(const char*));
MOCK_METHOD0(show_text, void());
};
//-------------------------------
//----- Test cases -------------
//----- Test cases -------------
TEST(TestShowTextMethod, CallDisplayOfmyTest){
Caller<MyTest> obj1;
obj1.call_show_text();
}
TEST(TestShowTextMethod, ReroutingDisplayToNewFunctionWithCallDisplay){
Caller<MockTest> obj2;
EXPECT_CALL(obj2.T, display("test_obj_2"))
.Times(1)
.WillOnce(Invoke(my_display));
obj2.call_display("test_obj_2");
}
TEST(TestShowTextMethod, ReroutingDisplayToNewFunctionWithCallShowText){
Caller<MockTest> obj3;
EXPECT_CALL(obj3.T, display("test_obj_3"))
.Times(1)
.WillOnce(Invoke(my_display));
obj3.call_display("test_obj_3");
}
TEST(TestShowTextMethod, ReroutingToNewFunctionWithCallShowText){
const char * str = "INSIDE MYTEST";
Caller<MockTest> obj4;
EXPECT_CALL(obj4.T, show_text());
EXPECT_CALL(obj4.T, display(str))
.Times(1)
.WillOnce(Invoke(my_display));
obj4.call_show_text();
}
//-------------------------------
//--- Initialization for test ----
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
只关注第四个测试,我认为 Gmock 可以处理第四个测试:show_text
调用 display
,为什么我不能在这种情况下模拟 display
? Gmock im是否可以模拟一个方法在同一个方法中调用另一个方法class or 我在第4个中犯了一定的错误测试用例 ?我得到了这样一个失败的测试结果:
../test_program.cpp:100: Failure
Actual function call count doesn't match EXPECT_CALL(obj4.T, display(str))...
Expected: to be called once
Actual: never called - unsatisfied and active
当然,show_text
和display()
是完全一样的调用。
有人有想法吗?
why I can't mock
display
in this case?
您不仅成功地模拟了 display
,而且还模拟了 show_text
。你不应该依赖模拟实现的行为,因为它不会被调用。
Is Gmock impossible to mock a method is called in another method in the same class.
这是可能的,但远非完美,您可以在下面找到示例。请注意,仅针对测试进行了一些权衡。使 DisplayController::display 成为虚拟 class 可能是最大的一个。
class DisplayController
{
public:
virtual void display(const std::string& text)
{
cout << text << endl;
}
void show_str(const std::string& text)
{
cout << "Start" << endl;
display(text);
cout << "End" << endl;
}
};
class TestableDisplayController : public DisplayController
{
public:
MOCK_METHOD1(display, void(const std::string&));
MOCK_METHOD1(show_str_called, void(const std::string&));
void show_str(const std::string& text)
{
show_str_called(text);
DisplayController::show_str(text);
}
};
template <typename T>
class ClassUnderTest
{
public:
ClassUnderTest(T& display)
: displayController(display)
{}
void callDirectDisplay(const std::string& text)
{
displayController.display(text);
}
void callIndirectDisplay(const std::string& text)
{
displayController.show_str(text);
}
private:
T& displayController;
};
TEST(test, example)
{
TestableDisplayController mockedDisplayController;
ClassUnderTest<TestableDisplayController> sut(mockedDisplayController);
std::string l_directDisplay = "directDisplay";
std::string l_indirectDisplay = "indirectDisplay";
EXPECT_CALL(mockedDisplayController, display(l_directDisplay));
sut.callDirectDisplay(l_directDisplay);
EXPECT_CALL(mockedDisplayController, display(l_indirectDisplay));
EXPECT_CALL(mockedDisplayController, show_str_called(l_indirectDisplay));
sut.callIndirectDisplay(l_indirectDisplay);
}