Tuesday, March 20, 2012

Matcher maker Matcher maker .... make me a Matcher

Ran into a problem at work today that we as a pair were close to giving up on before we finally came across the solution. We had an existing test that was ensuring that our mocked method was called with a pointer argument.

Here is that test:
using ::testing::Return;

TEST(MessageDataTests, SendResponseIsCalledWithMap)
{
    CString messageId = "TestMessageId";
    TXMLDataMap* xmlDataMap = new TXMLDataMap();
    (*xmlDataMap)["MsgId"] = messageId;

    MockTranslator *translator = new MockTranslator();
    EXPECT_CALL(*translator, SendResponse(xmlDataMap))
        .WillOnce(Return());
    translator->GetMessageData(xmlDataMap);
}

As you can see, this test is just ensuring that when SendResponse is called, it is called with the pointer xmlDataMap. We needed to add an expectation on part of what xmlDataMap was pointing too. Google Mock can accomplish this with Pointee(m) where m is a Matcher. Our pointer is not a simple type so we had to create our own matcher to check to see if our map contained the item we were adding inside of GetMessageData.

Here is what the final code looked like:
using ::testing::Return;
using ::testing::Pointee;
using ::testing::AllOf;

MATCHER_P(MapContainsValue, valueToCheck, "")
{
    return (arg.find(valueToCheck) != arg.end());
}

TEST(MessageDataTests, MapContainsDataWhenSendResponseIsCalled)
{
    CString messageId = "TestMessageId";
    TXMLDataMap* xmlDataMap = new TXMLDataMap();
    (*xmlDataMap)["MsgId"] = messageId;

    MockTranslator *translator = new MockTranslator();
    EXPECT_CALL(*translator, SendResponse(
        Pointee(AllOf(MapContainsValue("MsgId"),
                      MapContainsValue("Data")))))
        .WillOnce(Return());
    translator->GetMessageData(xmlDataMap);
}

No comments:

Post a Comment