匹配提升:UT中没有

时间:2015-08-06 08:30:20

标签: c++ implicit-conversion googletest googlemock gmock

我有公共职能:

virtual void foo(boost::optional<bar> p_param) = 0;

和它的模拟:

MOCK_METHOD1(foo, void(boost::optional<bar>));  

当我写下这样的期待电话时:

EXPECT_CALL(aMock, foo(boost::none));

我收到错误:

 error: no matching function for call to 'testing::StrictMock<AMockClass>::gmock_foo(bar boost::detail::none_helper::* const&)'

有信息:

note: no known conversion for argument 1 from 'const none_t {aka int boost::detail::none_helper::* const}' to 'const testing::Matcher<boost::optional<bar> >&'

然而,当expect-call的arg被Eq matcher包裹时:

EXPECT_CALL(aMock, foo(Eq(boost::none)));

代码编译得很好。什么是根本原因?

1 个答案:

答案 0 :(得分:3)

你的第一种方法不起作用,因为:

  1. MOCK_[CONST]..._METHOD[0..9]()在Mock类中生成两个函数 - 一个显而易见的 - 模拟方法的实现和一个名为gmock_MockedFunction的EXPECT_CALL调用的函数 - 在本例中为gmock_foo
  2. 这样生成的方法需要作为参数Matcher<T>对象 - 在您的情况下为单Matcher<boost::optional<bar>>
  3. Matcher<T>有两个构造函数 - 一个是显式的 - 所以它不会在你的情况下使用 - 而且一个隐含的期望值为T。
  4. 要从T1转换为T2(在您的情况下从boost::none_t转换为Matcher<boost::optional<bar>> - 编译器需要使用两个用户定义的转换 - 从boost::none_tboost::optional<bar>,然后从boost::optional<bar>Matcher<boost::optional<bar>> - 两个转换(作为构造函数)都存在 - 但C ++只允许在此类转换列表中使用一个用户定义的转换 - 请参阅this answer
  5. FYI gmock专门针对字符串类型使用Matcher来允许来自原始字符串的隐式构造:
  6. 见这个

    template <>
    class Matcher<internal::string>
        : public internal::MatcherBase<internal::string> {
     public:
      Matcher() {}
    
      explicit Matcher(const MatcherInterface<internal::string>* impl)
          : internal::MatcherBase<internal::string>(impl) {}
    
      // Allows the user to write str instead of Eq(str) sometimes, where
      // str is a string object.
      Matcher(const internal::string& s);  // NOLINT
    
      // Allows the user to write "foo" instead of Eq("foo") sometimes.
      Matcher(const char* s);  // NOLINT
    };
    

    然后 - 为什么它适用于Eq(boost :: none)?

    1. Eq(x)(其中x的类型为X)是一个返回::testing::internal::EqMatcher<X>的函数 - 在本例中为internal::EqMatcher<boost::none_t> - 所以这是您传递给gmock_foo(Matcher<boost::optional<bar>>的对象类型
    2. ::testing::internal::EqMatcher<X>可转换(通过用户定义的隐式转换运算符)到Matcher<Y>,其中Y是您想要的任何类型 - 例如你可以将Eq(8)转换为Matcher<std::string> - 在力量的安全方面:某些std :: enable_if(is_comparable)gmock应该使用...)
    3. 是的 - 满足单用户定义转换的规则 - 因为此转换运算符是编译器用于从内部:: EqMatcher转换为Matcher的唯一转换
    4. 我认为gmock知道boost库并且有一些特殊化就好了 - 因为它有std :: string - 所以你可以编写EXPECT_CALL(mock,foo(&#34; Hello&#34; ))对于期望std :: string的函数。以同样的方式,它可以是Matcher的专业化&gt;允许在你的问题中按预期写作。让gmock伙计们问一下......

      <强> [UPDATE]

      我在gmock forum中提出了这个问题 - 到目前为止没有热情......可以预期他们不希望与非标准库有如此强烈的关系,比如提升。当可选项是标准的时候,我将回到主题 - 现在我看到它是experimental ...