1

I have a C++ class I am attempting to test with GMock. I have the following mock class:

class MyTestMock
{
    public:
        MOCK_METHOD1(myCoolMethod, int(const char*));
        MOCK_METHOD1(myCoolMethod, int(string));
}

Then in my test the following happens:

MyTestMock myMock;
if ( myMock.myCoolMethod("stuff") )
{
    // Stuff I don't care about, don't want to execute
}
if ( myMock.myCoolMethod("moarStuff") )
{
    // More stuff I don't care about, don't want to execute
}
if ( myMock.myCoolMethod("foo") )
{
    // This I care about and want to execute
}

What I would like to do is allow the first two calls to be uninteresting calls that return the default for integers, 0, while I set up a specific expectation on the third call to return 1. This was my attempt to do so:

EXPECT_CALL(myMock, myCoolMethod(TypedEq<const char *>("foo"))).WillOnce(Return(1));

However, this ends up making the test fail. If I do this instead:

EXPECT_CALL(myMock, myCoolMethod(Matcher<const char *>(_))).WillRepeatedly(Return(0));
EXPECT_CALL(myMock, myCoolMethod(TypedEq<const char *>("foo"))).WillOnce(Return(1));

my test passes fine. I am attempting to make unit testing as painless as possible on an old, massive, monolithic-style codebase, so I'd really like to not need the extra magic line to tell it to return the default value. Any ideas on how I can do this with just the one expectation without tanking my test?

273K
  • 29,503
  • 10
  • 41
  • 64
Dustin Wilhelmi
  • 1,769
  • 2
  • 13
  • 27

1 Answers1

1

I guess my answer is not very "expected" for testing "an old, massive, monolithic-style codebase" with possible huge numbers of such CoolMethods..., but, unfortunately this is how google-mock works. As you can read in their FAQ:

Having an ON_CALL in the set-up part of a test doesn't mean that the calls are expected. If there's no EXPECT_CALL and the method is called, it's possibly an error. If we quietly let the call go through without notifying the user, bugs may creep in unnoticed.

The same is with "default" ON_CALL - I mean when you did not write explicitly ON_CALL because default value for a type (in your case 0 for int) is perfectly OK.

My advice is to always put such general expectation in SetUp function of your test suite - this way your test cases are not overloaded with many magic expectations:

class MyTestSuite : public ::testing::Test
{
protected:
    MyTestMock myMock;
    void SetUp() override
    {
        EXPECT_CALL(myMock, myCoolMethod(Matcher<const char *>(_))).WillRepeatedly(Return(0));
    }   
};

This way you have "annoying" lines only in one place, and your test cases are "clear":

TEST_F(MyTestSuite, shallDoSomethingWhenCoolMethodAcceptsFoo)
{
   EXPECT_CALL(myMock, myCoolMethod(TypedEq<const char *>("foo"))).WillOnce(Return(1));
}
TEST_F(MyTestSuite, shallDoSomethingElseWhenCoolMethodAcceptsMoarStuff)
{
   EXPECT_CALL(myMock, myCoolMethod(TypedEq<const char *>("moarStuff"))).WillOnce(Return(1));
}
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • The thing is, though, that it works fine if I don't set any expectations at all. The error isn't that it is called without an expectation, it is that it is called more times than the expectation specified, even though my expectation limited it with a TypedEq. – Dustin Wilhelmi Oct 28 '15 at 03:21
  • Good practice is to always wrap Mock with `StrictMock` or `NiceMock`. In your case I'd use `StrictMock` as you are interested in how this very mock behaves. `NiceMock` are for mocks that are required by you tested code - but you do not really use them in your tests. Your case is a little more complicated because in some aspects it should be StrictMock (for calling with "foo") for other it should be NiceMock. Such "dualism" is solved by specifying this general expectations for NiceMock aspects of your mock.. – PiotrNycz Oct 28 '15 at 09:41