GTest的嵌套Matchers

时间:2018-02-26 12:08:45

标签: c++ googletest googlemock gmock

我想在其他匹配器中使用一些现有的匹配器。我知道MatcherInterface解决方案,但我想知道我可以使用由MATCHER_P定义的匹配器。如果找到这个解决方案:

struct Foo
{
    double x;
    double y;
};

struct Bar
{
    Foo foo;
    int i;
};

MATCHER_P(EqFoo, foo, "")
{
    ::testing::Matcher<double> x_matcher = ::testing::DoubleNear(foo.x, 0.0001);
    if (!x_matcher.MatchAndExplain(arg.x, result_listener))
    {
        return false;
    }

    ::testing::Matcher<double> y_matcher = ::testing::DoubleNear(foo.y, 0.0001);
    if (!y_matcher.MatchAndExplain(arg.y, result_listener))
    {
        return false;
    }

    return true;
}

MATCHER_P(EqBar, bar, "")
{
    ::testing::Matcher<Foo> foo_matcher = EqFooMatcherP<Foo>(bar.foo);

    if (!foo_matcher.MatchAndExplain(arg.foo, result_listener))
    {
        return false;
    }

    if (bar.i != arg.i)
    {
        return false;
    }

    return true;
}

TEST_F(TestClass, BarTest)
{
    Bar bar_val{{10.12, 76.43}, 78};
    Bar bar_exp{{10.12, 99.99}, 78};

    EXPECT_THAT(bar_val, EqBar(bar_exp));
}

我只是想知道,有没有更好更好的解决方案

  • 在另一个中使用我自己的MATCHER_P匹配器
  • 在另一个中使用原始GTest匹配器。

1 个答案:

答案 0 :(得分:2)

正确的方法是尽可能使用gtest / gmock中的匹配器。只有在没有提供匹配器的情况下 - 使用您自己的匹配器。

在你的例子中 - 它就像这样简单:

auto EqFoo(const Foo& expected)
{
   return ::testing::AllOf(
         ::testing::Field(&Foo::x, ::testing::DoubleNear(expected.x, 0.0001)),
         ::testing::Field(&Foo::y, ::testing::DoubleNear(expected.y, 0.0001))
     );
}

auto EqBar(const Bar& expected)
{
   return ::testing::AllOf(
         ::testing::Field(&Bar::foo, EqFoo(expected.foo)),
         ::testing::Field(&Bar::i, expected.i)
     );
}

更一般的方法是使用重载:

auto MatchDouble(double expected)   
{
    return ::testing::DoubleNear(expected.x, 0.0001);
}
auto MatchFoo(::testing::Matcher<double> x, ::testing::Matcher<double> y)
{
   return ::testing::AllOf(
         ::testing::Field(&Foo::x, x),
         ::testing::Field(&Foo::y, y)
     );
}
auto MatchFoo(double x, double y)
{
   return MatchFoo(MatchDouble(x), MatchDouble(y));
}

auto MatchBar(::testing::Matcher<Foo> foo, ::testing::Matcher<int> i)
{
   return ::testing::AllOf(
         ::testing::Field(&Bar::foo, foo),
         ::testing::Field(&Bar::i, expected.i),
     );
}
auto MatchBar(const Bar& expected)
{
   return MatchBar(expected.foo, expected.i);
}

所以你的测试:

TEST_F(TestClass, BarTest)
{
    Bar bar_val{{10.12, 76.43}, 78};
    Bar bar_exp{{10.12, 99.99}, 78};

    EXPECT_THAT(bar_val, MatchBar(bar_exp));

    // or - e.g. you can match only Bar::y if other things are irrelevant in your test
    EXPECT_THAT(bar_val, MatchBar(MatchFoo(_, MatchDouble(2.001)), _);
}

无论如何 - 使用MATCHER_P应该是相当罕见的情况,我自己的观察是这个宏真的被过度使用了。

如果您的项目是C ++之前的14 - 使用::testing::Matcher<T>而不是auto作为所有这些函数的返回类型。