Search code examples
c++googlemock

Testing the contents in std::unordered_map without worrying about the order


I am looking to check whether the strings outputted match against the expected one without worrying about the order in which they are printed.

Here, std::unordered_map stores the A objects as values and since it's not ordered, it becomes tricky since the output can be either foo\nbar\n or bar\nfoo\n.

Any ways it could be tested in google mock?

class A
{
    std::string _name;

    public:
    A(std::string name) : _name(name) {}
    void foo() 
    {
        std::cout << _name << "\n";
    }
};

TEST(UnorderedMatch, A) 
{
    A a1{"foo"};
    A a2{"bar"};
    std::string expectedOut = "foo\nbar\n"; 
    std::unordered_map<int, A> m1 = { {1, a1}, {2, a2} };

    // test: foo()'s output matches expectedOut
    // verify output is "foo\nbar\n" without worrying about its order 
    for (auto e : m1)
    {
        e.second.foo();
    }
}

Solution

  • Assuming that by verification you mean using gmock instruments, you could employ UnorderedElementsAre mentioned here. Otherwise refer to advice given in the comments.

    Please note that using UnorderedElementsAre requires a comparison operator in A, so I've changed its definition a bit:

    class A
    {
        std::string _name;
    
    public:
        auto operator<=>(A const&) const = default; // required by test
        A(std::string name) : _name(name) {}
        // ...
    };
    

    Example of UnorderedElementsAre usage:

    TEST(UnorderedMatch, A)
    {
        A a1{"foo"};
        A a2{"bar"};
    
        std::unordered_map<int, A> m1 = { {1, a1}, {2, a2}, };
    
        using namespace ::testing;
        using std::string_literals::operator""s;
    
        EXPECT_THAT(m1, UnorderedElementsAre( Pair(_, "bar"s), Pair(_, "foo"s) ));
    }