How to use Given/When/Then pattern with mocks (Google Mock)?

c++, googlemock, googletest, unit-testing

Solution

The `EXPECT_CALL` macro can be thought of as a way of testing interaction between a class and another class. As such, if you are using it with another `EXPECT` macro, then your test is likely testing two things, which is why it appears to conflict with the "Given-When-Then" paradigm (also known as "Arrange-Act-Assert").

If you just need to set up some behavior on your mock object for testing, use the `ON_CALL` macro instead:

TEST(TestFixture, TestName)
{
    // Given
    int a = 5;
    int b = 6;
    int expectedResult = 30;

    MightCalculatorMock mock;

    ON_CALL(mock, multiply(a,b))
        .WillByDefault(Return(expectedResult));

    // When
    int result = Multiply(mock, a, b);

    // Then
    EXPECT_EQ(expectedResult, result);
}

If you are actually looking to test the iteraction between your system under test and some other collaborator, you can use an "Arrange-Expect-Act" pattern:

TEST(TestFixture, CalculatorIsCalledProperly)
{
    // Arrange
    int a = 5;
    int b = 6;
    int expectedResult = 30;
    MightCalculatorMock mock;

    // Expect
    EXPECT_CALL(mock, multiply(Eq(a),Eq(b)));

    // Act
    int result = Multiply(mock, a, b);
}

Problem

I'm using the Given/When/Then pattern to make test code much clearer. Since I'm writing those tests in C++ I chosed to use Google Test. With tests the pattern is clear, because I do sth like this: ``` TEST(TestFixture, TestName) { // Given int a = 5; int b = 6; int expectedResult = 30; // When int result = Multiply(a, b); // Then EXPECT_EQ(expectedResult, result); } ``` But with mocks it stops being clear since there appear some EXPECTs in the Given part. The Given part suppose to be a setup step. Please see an example: ``` TEST(TestFixture, TestName) { // Given int a = 5; int b = 6; int expectedResult = 30; MightCalculatorMock mock; EXPECT_CALL(mock, multiply(a,b)) .WillOnce(Return(expectedResult)); // When int result = Multiply(mock, a, b); // Then EXPECT_EQ(expectedResult, result); } ``` Is this approach correct? How the Given/When/Then comments should be placed in the test code, where?

Original source