Search code examples
c++googletestgooglemock

How to use google tests's container matchers to check ValueObjects exist in a container?


I have this exercise in C# that I'm trying to translate to C++. I'd like to have some google tests using matchers to check the collection contents like I can in C#. The elements in the container are a user-defined ValueObject that has implemented the == operator so objects with the same data are equal.

It doesn't work and I don't know why?

This is what I want to write:

    std::vector<Character *> charactersList = finder.FindFamilyByLastName("Wheeler");
    ASSERT_THAT(charactersList, testing::Contains(*std::make_unique<Character>("Nancy", "Wheeler")));
    ASSERT_THAT(charactersList, testing::ElementsAre(
            *std::make_unique<Character>("Nancy", "Wheeler"),
            *std::make_unique<Character>("Mike", "Wheeler"),
            *std::make_unique<Character>("Karen", "Wheeler")
    ));

That's a snippet from: https://github.com/emilybache/StrangeCharacter-TestDesign-Kata/blob/main/cpp/test-gtest/ExampleCharacterTestCase.cpp

This is the C# version that does work:

    CollectionAssert.Contains(charactersList, new Character("Nancy", "Wheeler"));
    CollectionAssert.AreEquivalent(new List<Character>()
    {
        new Character("Nancy", "Wheeler"),
        new Character("Mike", "Wheeler"),
        new Character("Karen", "Wheeler"),
    }, charactersList);

That's a snippet from: https://github.com/emilybache/StrangeCharacter-TestDesign-Kata/blob/main/csharp/StrangeCharacters/TestCharacters/ExampleCharacterTestCase.cs


Solution

  • Here

            std::vector<Character *> charactersList = finder.FindFamilyByLastName("Wheeler");
    

    you have vector of pointers.

            ASSERT_THAT(charactersList, testing::Contains(*std::make_unique<Character>("Nancy", "Wheeler")));
    

    Here you are trying compare elements of that array (a pointer) to a value, which is understandable for someone who uses C# more. In C++ this types are not comparable. You where aware of pointer and added this performance killer *make_unique which is also form of over-engineering.

    You need to compose matchers to access value from pointer. There is a matcher testing::Pointee:

            ASSERT_THAT(charactersList, testing::Contains(testing::Pointee(Character("Nancy", "Wheeler"))));
    

    Same thing should be done for ElementsAre (there is better way but to advanced).

    Here is live demo: https://godbolt.org/z/ocTx5hf6W