googlemock - 模拟返回具有多个用户定义转换的类型的方法

时间:2018-04-06 09:40:10

标签: c++ googlemock

我正在为新组件编写单元测试,其中一个接口方法返回一个具有多个用户定义转换的对象。在模拟这样的方法时,似乎编译器抱怨模棱两可:

gdpr1@BEL081089 ~/Code/sandbox/mocking
$ make && ./tests.exe
Scanning dependencies of target tests
[ 25%] Building CXX object CMakeFiles/tests.dir/Foo.cpp.o
[ 50%] Building CXX object CMakeFiles/tests.dir/FooTest.cpp.o
In file included from /cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest.h:58:0,
                 from /cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h:46,
                 from /cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/gmock-actions.h:46,
                 from /cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/gmock.h:58,
                 from /home/gdpr1/Code/sandbox/mocking/FooTest.cpp:1:
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/internal/gtest-internal.h: In instantiation of ‘const bool testing::internal::ImplicitlyConvertible<const Trouble&, long long int>::value’:
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest-printers.h:236:38:   required from ‘std::basic_ostream<_CharT, _Traits>& testing::internal2::operator<<(std::basic_ostream<_CharT, _Traits>&, const T&) [with Char = char; CharTraits = std::char_traits<char>; T = Trouble]’
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest-printers.h:285:7:   required from ‘void testing_internal::DefaultPrintNonContainerTo(const T&, std::ostream*) [with T = Trouble; std::ostream = std::basic_ostream<char>]’
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest-printers.h:476:49:   required from ‘void testing::internal::DefaultPrintTo(testing::internal::WrapPrinterType<(testing::internal::DefaultPrinterType)3u>, const T&, std::ostream*) [with T = Trouble; std::ostream = std::basic_ostream<char>]’
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest-printers.h:511:17:   required from ‘void testing::internal::PrintTo(const T&, std::ostream*) [with T = Trouble; std::ostream = std::basic_ostream<char>]’
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest-printers.h:762:12:   required from ‘static void testing::internal::UniversalPrinter<T>::Print(const T&, std::ostream*) [with T = Trouble; std::ostream = std::basic_ostream<char>]’
/cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/gmock-spec-builders.h:1385:31:   required from ‘void testing::internal::ActionResultHolder<T>::PrintAsActionResult(std::ostream*) const [with T = Trouble; std::ostream = std::basic_ostream<char>]’
/home/gdpr1/Code/sandbox/mocking/FooTest.cpp:21:1:   required from here
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/internal/gtest-internal.h:850:20: error: conversion from ‘const Trouble’ to ‘long long int’ is ambiguous
       sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
             ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/gdpr1/Code/sandbox/mocking/Bar.h:7:0,
                 from /home/gdpr1/Code/sandbox/mocking/FooTest.cpp:3:
/home/gdpr1/Code/sandbox/mocking/Foo.h:17:5: note: candidate: Trouble::operator int() const
     operator int() const { return value; }
     ^~~~~~~~
/home/gdpr1/Code/sandbox/mocking/Foo.h:16:5: note: candidate: Trouble::operator short int() const
     operator short() const { return value; }
     ^~~~~~~~
In file included from /cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/gtest.h:58:0,
                 from /cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h:46,
                 from /cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/gmock-actions.h:46,
                 from /cygdrive/c/GPDR1/Code/googletest/googlemock/include/gmock/gmock.h:58,
                 from /home/gdpr1/Code/sandbox/mocking/FooTest.cpp:1:
/cygdrive/c/GPDR1/Code/googletest/googletest/include/gtest/internal/gtest-internal.h:833:15: note:   initializing argument 1 of ‘static char testing::internal::ImplicitlyConvertible<From, To>::Helper(To) [with From = const Trouble&; To = long long int]’
   static char Helper(To);
               ^~~~~~
make[2]: *** [CMakeFiles/tests.dir/build.make:87: CMakeFiles/tests.dir/FooTest.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/tests.dir/all] Error 2
make: *** [Makefile:95: all] Error 2

这是一个显示问题的小文件:

的main.cpp

#include "gmock/gmock.h"
#include "gtest/gtest.h"

class Special
{
private:
    char value;

public:
    Special(char v) : value(v) {}

    operator short() const { return value; }
    operator int() const { return value; }
};

class Foo
{
public:
    virtual ~Foo() {};
    virtual Foo& foo() = 0;
    virtual Special getVariant() = 0;
};

class MockFoo : public Foo
{
public:
    MOCK_METHOD0(foo, Foo&());
    MOCK_METHOD0(getVariant, Special());
};

TEST(FooTest, callFoo)
{
    MockFoo myFoo;
    ::testing::DefaultValue<Foo&>::Set(myFoo);

    EXPECT_CALL(myFoo, foo()).Times(1);
    myFoo.foo();
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

我在Windows 7机器上使用Cygwin(CYGWIN_NT-6.1-WOW),gcc版本是6.4.0,我使用的是C ++ 98。我的cmake文件是:

的CMakeLists.txt

cmake_minimum_required (VERSION 3.6)
project (httpproperpty)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/build/bin)

include_directories("${PROJECT_BINARY_DIR}")
include_directories("/cygdrive/c/GPDR1/Code/googletest/googletest/include")
include_directories("/cygdrive/c/GPDR1/Code/googletest/googlemock/include")

LINK_DIRECTORIES("/cygdrive/c/GPDR1/Code/googletest/googlemock/")
LINK_DIRECTORIES("/cygdrive/c/GPDR1/Code/googletest/googlemock/gtest/")

# file(GLOB Source_files "*.cpp")

set(CMAKE_CXX_STANDARD 98)

add_executable(tests "main.cpp")
target_link_libraries (tests gtest gmock)

enable_testing()

add_test(NAME mytests
         COMMAND tests)

我已经搜索过,但找不到任何解决方案。关于如何解决这个问题的任何想法?我可以从用户定义的转换方法中删除const,但我怀疑这是一个正确的解决方案。无论如何,在我的实际代码中,我不能轻易地改变方法。

到目前为止,唯一的解决方案是使用存根而不是模拟返回此对象的方法(getVariant),但这在长队中并不是一个很好的解决方案。

1 个答案:

答案 0 :(得分:0)

上例中的解决方案是添加用户定义的转化以转换为long long int

operator long long int() const { return value; }

Special班级

class Special
{
private:
    char value;

public:
    Special(char v) : value(v) {}

    operator short() const { return value; }
    operator int() const { return value; }
    operator long long int() const { return value; }
};

这解决了歧义。存在歧义是因为Helper类想要将其转换为long long int,编译器可以选择将其转换为shortint,两者都可以转换到long long int