'How to mock private methods in a class which is being used by public methods in Google Test?
I have a class, say ClassA which has some public functions as well as private. The public functions in turns class private functions. Now my intention here is to test the private function via public function. For Public functions, I am trying to invoke the original implementation and for private method I am trying to create a Mock function.
My Class A is like this,
class ClassA {
public:
string getName(string key) {
int value = 2;
int code = getCode(value);
if(code != 2)
cout<<"Error";
else
return "XYZ";
}
private:
int getCode(int value) {
if(value == 2)
return 2;
else
return -1;
}
};
Now I have a Mock for the ClassA like this,
class MockA : public ClassA {
public:
MOCK_METHOD1(getName,string(string key)); //Mock for public method
MOCK_METHOD1(getCode,int(int value))l //Mock for private method
}
This is my GoogleTest test case,
TEST(ClassATest, Test1)
{
MockA a;
Class a1;
EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(2));
EXPECT_CALL(a,getName()).Times(1).WillOnce(Return(Invoke(&a1,
ClassA::getName());
}
As you can see, for the private method I am using mock and for public method I am using Invoke and invoking the original implementation.
Now, when I compile this code, I get an error,
Actual function call count doesn't match EXPECT_CALL(a,getCode()).... Expected : to be called once Actual : never called - unsatisfied and active
Now when I try to use orginal Implementation for getCode() also like,
EXPECT_CALL(a,getCode()).Times(1).WillOnce(Return(Invoke(&a1,
ClassA::getCode());
I get an compilation error saying getCode() is inaccesible which I think is expected.
By now, if you are reading this, hope you are understood my problem statement. I have to test the private method by passing in different arguments, via the public method which I test via gtest.
I wanted to mock the private method as stated by this article in github and call the orininal production code for my public method.
Am I doing something fundamentally wrong? If so, can any of you some better methods for my use case.
I have tried FRIEND_TEST and tbh, I dont want any modifications in my production code. I will try that as a last resort.
Solution 1:[1]
You are trying to invoke a private method from ClassA. This is not possible except if there is a friend declaration, but yes, it's not ideal.
The problem stems from the design of your test which should call a public API and not an implementation detail.
Solution 2:[2]
Late answer, but I'm currently working on similar issues and saw this question.
In your example I'm not quite sure what the purpose of Invoke() is, but if all you are trying to do is verify calls to getCode() and control its return value, then you would only need to mock that one.
You would have to modify the production code to make the private function virtual, so if that's not an option then of course this wouldn't work for you. It seems like a pretty safe modification though.
class ClassA {
public:
string getName(string key) {
int value = 2;
int code = getCode(value);
if (code != 2)
return "Error";
return "XYZ";
}
private:
virtual int getCode(int value) {
if (value == 2)
return 2;
return -1;
}
};
class MockA : public ClassA {
public:
MOCK_METHOD1(getCode, int(int value));
};
TEST(ClassATest, Test1)
{
MockA mockA;
EXPECT_CALL(mockA, getCode(2)).WillOnce(Return(2));
EXPECT_EQ(mockA.getName("key"), "XYZ");
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Matthieu Brucher |
| Solution 2 | Chris Olsen |
