I declare a function
void MyFunction(const std::wstring& inParameter, std::wstring& outParamater);
The first parameter is a passed in parameter, the second one is the value out parameter, the value I want to get by the function will pass it out by outParameter
.
Now I Gmock it
MOCK_METHOD2(MyFunction, void(const std::wstring&, std::wstring&));
However, when I use this mock function:
std::wstring firstStr = L"firstStr";
std::wstring test = L"test";
EXPECT_CALL(*myGmockInstance, MyFunction(firstStr, _)).Times(1).WillOnce(DoAll(firstStr, SetArgReferee<1>(test)));
It doesn't work.
I also tried
EXPECT_CALL(*myGmockInstance, MyFunction(_, _)).Times(1).WillOnce(DoAll(_, SetArgReferee<1>(test)));
or
EXPECT_CALL(*myGmockInstance, MyFunction(_, _)).Times(1).WillOnce(DoAll(firstStr, SetArgReferee<1>(test)));
or
EXPECT_CALL(*myGmockInstance, MyFunction(_, _)).Times(1).WillOnce(DoAll(SetArgReferee<0>(firstStr), SetArgReferee<1>(test)));
I understand that the inParameter
is const
, so I cannot use SetArgReferee
for it. But how to set its value and at the same time I can set value for outParameter
?
I think that the title of your question is quite misleading. From what I understand, you just want to assign some arbitrary value to your function's second argument (the output argument). This is how you can do it using Invoke
:
using ::testing::_;
void assignStringToArg(const std::wstring&, std::wstring& outputStr,
const std::wstring expectedStr) {
outputStr = expectedStr;
}
class SomeMock {
public:
MOCK_METHOD2(MyFunction, void(const std::wstring&, std::wstring&));
};
TEST(xxx, yyy) {
SomeMock someMock;
std::wstring firstStr(L"aaabbbccc");
std::wstring secondStr(L"I should change upon MyFunction call ...");
std::wstring expectedSecondStr(L"xxxyyyzzz");
EXPECT_CALL(someMock, MyFunction(firstStr, _)).Times(1).WillOnce(Invoke(std::bind(
&assignStringToArg,
std::placeholders::_1,
std::placeholders::_2,
expectedSecondStr)));
someMock.MyFunction(firstStr, secondStr);
ASSERT_EQ(expectedSecondStr, secondStr);
}
Note that the function provided to Invoke
must have the same signature as the function that you expect to be called (that's why I use bind
). You can achieve the same result using google macro ACTION_P
. I prefer to use Invoke
only because it looks more clean to me.
Since your case is rather simple, you can also do it using SetArgReferee
like you tried before:
EXPECT_CALL(someMock, MyFunction(firstStr, _)).Times(1).WillOnce(
SetArgReferee<1>(L"something"));
someMock.MyFunction(firstStr, secondStr);
ASSERT_EQ(L"something", secondStr);
I just see no point using DoAll
if you only want to do one action. But ... if you really insist:
EXPECT_CALL(someMock, MyFunction(firstStr, _)).Times(1).WillOnce(
DoAll(SetArgReferee<1>(L"something1"), SetArgReferee<1>(L"something2")));
someMock.MyFunction(firstStr, secondStr);
ASSERT_EQ(L"something2", secondStr);
It is rather stupid example, because it set's the output variable to L"something1"
and then immediately to L"something2"
.