Search code examples
c++pointerscontainersgooglemockmatcher

Gmock Element Matcher for Container of Pointers


In my unit tests, I want to test that a GameLauncher creates a Game containing some Objects, based on CharacterSelections. In Java-flavoured pseudocode, the test would be:

Game game = gameLauncher.createGame(characterSelections);

assertThat(game.getObjects(), containsInAnyOrder(c1, c2, c3));

As I am working in c++, game->getObjects() returns a vector<Object*>. I am using a vector of pointers as Object is a polymorphic type.

GMock#ContainerMatchers gives a list of matchers for containers. Since STL containers use the operator== to determine equality between its elements (see github/cpp-container-equality), I cannot simply use UnorderedElementsAre(...) as this will perform pointer comparisons.

What are my options?

// redacted includes

class GameLauncherTest : public testing::Test {
    // ... redacted ...
};

TEST_F(GameLauncherTest, launchesGameWithCharacterInstanceForSelectedCharacters) {
    auto const characterSelections = new CharacterSelections();
    characterSelections->add(new CharacterSelection(0, false, 1));
    characterSelections->add(new CharacterSelection(3, false, 0));
    characterSelections->add(new CharacterSelection(2, true, 1));

    Game* const game = this->gameLauncher->launchGame(characterSelections);

    auto const character0 = new Character(0, objectData1);
    auto const character1 = new Character(1, objectData0);
    auto const character2 = new Character(2, objectData1);

    const vector<Object*> inGameObjects = game->getObjects();

    // fails
    EXPECT_THAT(inGameObjects, UnorderedElementsAre(character0, character1, character2));

    delete character0;
    delete character1;
    delete character2;
    delete characterSelections;
}

Solution

  • You can use the Pointee matcher to dereference the pointers:

    EXPECT_THAT(inGameObjects,
                UnorderedElementsAre(Pointee(*character0),
                                     Pointee(*character1),
                                     Pointee(*character2)));