-2

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();
    }
}
E_net4
  • 27,810
  • 13
  • 101
  • 139
xyf
  • 664
  • 1
  • 6
  • 16
  • 2
    How about collecting the values into a sorted collection, and then checking the sorted output? – Brian61354270 Mar 10 '23 at 19:03
  • Either sort before outputting, or avoid checking the output and straight compare m1 with an unordered map containing the expected values. – Matteo Italia Mar 10 '23 at 19:05
  • Which part of this demonstration is the test and which part is the code being tested? – user253751 Mar 10 '23 at 19:07
  • @Brian61354270 true but I wouldn't want to use `std::map` in the production just so I could test it since logically the items aren't supposed to be ordered – xyf Mar 10 '23 at 19:08
  • @user253751 the output to the stream by `e.second.foo()` is being tested against `expectedOut` – xyf Mar 10 '23 at 19:13
  • @xyf Then your problem is that the test is calling `e.second.foo()` in an unknown order. So have you considered simply changing the test? maybe you put them in a vector instead of an unordered_map? or you call m1[1].foo(); m1[2].foo(); ? – user253751 Mar 10 '23 at 19:14
  • @xyf I think you've misunderstood @Brian61354270. He wasn't saying to switch to `std::map` in your production code. He was saying in the *test* copy over the items from your unordered collection to an ordered collection and *then* perform your test. – WBuck Mar 10 '23 at 19:49

1 Answers1

3

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) ));
}
George-Ber
  • 46
  • 1
  • 5