在Google测试中创建模拟类的向量

时间:2018-07-20 20:44:47

标签: c++ unit-testing stl googletest

是否可以在Google Test / Mock中构建模拟对象的向量?我有一种情况,我想从对象(Foo)返回自定义对象(Bar)的向量。因此,我正在尝试使用该类的模拟版本(std::vector<Foo>)返回向量。示例代码-

class Foo {
public:

    virtual int op(int a , int b) {
        return 0;
    }
};

class Bar {
public:
    virtual std::vector<Foo> getFoos() {

        std::vector<Foo> v;
        // ...
        // Some logic to fill this vector
        // ...

        return v;
    }
};


class MockFoo : public Foo {
public:
    MOCK_METHOD2(op, int(int, int));
};


class MockBar : public Bar {
public:
    MOCK_METHOD0(getFoos, std::vector<Foo>());
};



TEST(Foo, test_op) {
    vector<MockFoo> v;

    v.emplace_back();

    ASSERT_EQ(v.size(), 1);

    MockBar bar;

    EXPECT_CALL(bar, getFoos())
            .WillRepeatedly(Return(v));
}

我得到了

In file included from .../googlemock/include/gmock/gmock.h:58:0,
                 from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-actions.h: In instantiation of ‘testing::internal::ReturnAction<R>::Impl<R_, F>::Impl(const testing::internal::linked_ptr<T>&) [with R_ = std::vector<MockFoo>; F = std::vector<Foo>(); R = std::vector<MockFoo>]’:
.../googlemock/include/gmock/gmock-actions.h:557:44:   required from ‘testing::internal::ReturnAction<R>::operator testing::Action<Func>() const [with F = std::vector<Foo>(); R = std::vector<MockFoo>]’
.../FooBarTest.cpp:65:38:   required from here
.../googlemock/include/gmock/gmock-actions.h:577:39: error: no matching function for call to ‘ImplicitCast_(std::vector<MockFoo>&)’
           value_(ImplicitCast_<Result>(value_before_cast_)) {}
                                       ^
In file included from .../googletest/include/gtest/internal/gtest-internal.h:40:0,
                 from .../googletest/include/gtest/gtest.h:58,
                 from .../FooBarTest.cpp:1:
.../googletest/include/gtest/internal/gtest-port.h:1343:11: note: candidate: template<class To> To testing::internal::ImplicitCast_(To)
 inline To ImplicitCast_(To x) { return x; }
           ^
.../googletest/include/gtest/internal/gtest-port.h:1343:11: note:   template argument deduction/substitution failed:
In file included from .../googlemock/include/gmock/gmock.h:58:0,
                 from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-actions.h:577:39: note:   cannot convert ‘((testing::internal::ReturnAction<std::vector<MockFoo> >::Impl<std::vector<MockFoo>, std::vector<Foo>()>*)this)->testing::internal::ReturnAction<std::vector<MockFoo> >::Impl<std::vector<MockFoo>, std::vector<Foo>()>::value_before_cast_’ (type ‘std::vector<MockFoo>’) to type ‘std::vector<Foo>’
           value_(ImplicitCast_<Result>(value_before_cast_)) {}
                                       ^
In file included from /usr/include/c++/5/vector:62:0,
                 from .../googletest/include/gtest/gtest.h:56,
                 from .../FooBarTest.cpp:1:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = MockFoo; _Args = {const MockFoo&}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:75:18:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const MockFoo*, std::vector<MockFoo> >; _ForwardIterator = MockFoo*; bool _TrivialValueTypes = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:126:15:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const MockFoo*, std::vector<MockFoo> >; _ForwardIterator = MockFoo*]’
/usr/include/c++/5/bits/stl_uninitialized.h:281:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const MockFoo*, std::vector<MockFoo> >; _ForwardIterator = MockFoo*; _Tp = MockFoo]’
/usr/include/c++/5/bits/stl_vector.h:322:31:   required from ‘std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = MockFoo; _Alloc = std::allocator<MockFoo>]’
.../FooBarTest.cpp:65:37:   required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: use of deleted function ‘MockFoo::MockFoo(const MockFoo&)’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
.../FooBarTest.cpp:40:7: note: ‘MockFoo::MockFoo(const MockFoo&)’ is implicitly deleted because the default definition would be ill-formed:
 class MockFoo : public Foo {
       ^
.../FooBarTest.cpp:40:7: error: use of deleted function ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(const testing::internal::FunctionMocker<int(int, int)>&)’
In file included from .../googlemock/include/gmock/gmock.h:61:0,
                 from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: note: ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(const testing::internal::FunctionMocker<int(int, int)>&)’ is implicitly deleted because the default definition would be ill-formed:
 class FunctionMocker<R(A1, A2)> : public
       ^
In file included from .../googletest/include/gtest/internal/gtest-internal.h:40:0,
                 from .../googletest/include/gtest/gtest.h:58,
                 from .../FooBarTest.cpp:1:
.../googlemock/include/gmock/gmock-spec-builders.h:1784:35: error: ‘testing::internal::FunctionMockerBase<F>::FunctionMockerBase(const testing::internal::FunctionMockerBase<F>&) [with F = int(int, int)]’ is private
   GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
                                   ^
.../googletest/include/gtest/internal/gtest-port.h:875:3: note: in definition of macro ‘GTEST_DISALLOW_COPY_AND_ASSIGN_’
   type(type const &);\
   ^
In file included from .../googlemock/include/gmock/gmock.h:61:0,
                 from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: error: within this context
 class FunctionMocker<R(A1, A2)> : public
       ^
In file included from /usr/include/c++/5/vector:62:0,
                 from .../googletest/include/gtest/gtest.h:56,
                 from .../FooBarTest.cpp:1:
/usr/include/c++/5/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = MockFoo; _Args = {MockFoo}]’:
/usr/include/c++/5/bits/stl_uninitialized.h:75:18:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MockFoo*>; _ForwardIterator = MockFoo*; bool _TrivialValueTypes = false]’
/usr/include/c++/5/bits/stl_uninitialized.h:126:15:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<MockFoo*>; _ForwardIterator = MockFoo*]’
/usr/include/c++/5/bits/stl_uninitialized.h:281:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<MockFoo*>; _ForwardIterator = MockFoo*; _Tp = MockFoo]’
/usr/include/c++/5/bits/stl_uninitialized.h:303:2:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = MockFoo*; _ForwardIterator = MockFoo*; _Allocator = std::allocator<MockFoo>]’
/usr/include/c++/5/bits/vector.tcc:422:8:   required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {}; _Tp = MockFoo; _Alloc = std::allocator<MockFoo>]’
/usr/include/c++/5/bits/vector.tcc:101:23:   required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = MockFoo; _Alloc = std::allocator<MockFoo>]’
.../FooBarTest.cpp:56:20:   required from here
/usr/include/c++/5/bits/stl_construct.h:75:7: error: use of deleted function ‘MockFoo::MockFoo(MockFoo&&)’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
.../FooBarTest.cpp:40:7: note: ‘MockFoo::MockFoo(MockFoo&&)’ is implicitly deleted because the default definition would be ill-formed:
 class MockFoo : public Foo {
       ^
.../FooBarTest.cpp:40:7: error: use of deleted function ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(testing::internal::FunctionMocker<int(int, int)>&&)’
In file included from .../googlemock/include/gmock/gmock.h:61:0,
                 from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: note: ‘testing::internal::FunctionMocker<int(int, int)>::FunctionMocker(testing::internal::FunctionMocker<int(int, int)>&&)’ is implicitly deleted because the default definition would be ill-formed:
 class FunctionMocker<R(A1, A2)> : public
       ^
In file included from .../googletest/include/gtest/internal/gtest-internal.h:40:0,
                 from .../googletest/include/gtest/gtest.h:58,
                 from .../FooBarTest.cpp:1:
.../googlemock/include/gmock/gmock-spec-builders.h:1784:35: error: ‘testing::internal::FunctionMockerBase<F>::FunctionMockerBase(const testing::internal::FunctionMockerBase<F>&) [with F = int(int, int)]’ is private
   GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
                                   ^
.../googletest/include/gtest/internal/gtest-port.h:875:3: note: in definition of macro ‘GTEST_DISALLOW_COPY_AND_ASSIGN_’
   type(type const &);\
   ^
In file included from .../googlemock/include/gmock/gmock.h:61:0,
                 from .../FooBarTest.cpp:2:
.../googlemock/include/gmock/gmock-generated-function-mockers.h:106:7: error: within this context
 class FunctionMocker<R(A1, A2)> : public

据我所知,这是因为Google测试模拟类不可复制。我明确不需要可复制的模拟类。我只需要能够返回模拟对象列表。是否可以在Google测试(release-1.8.0)中进行?

想到的一个替代方法是在Bar中实现类似patter的迭代器,使其表现得像矢量。但是,如果可能的话,我想避免这种方法。在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您需要在Mockclass中实现一个复制构造函数,这就是我设法创建模拟类向量的方式。大概是这样的:

MockClass(const MockClass& other) {
                    setDefaultBehaviors();

                    defaultId = other.defaultId;
                }

希望有帮助。 :)