0

Is it possible to build a vector of mocked objects in Google Test/Mock? I have a scenario, where I want to return a vector of custom objects (Foo) from an object (Bar). So I was trying return vector with mocked version of that class (std::vector<Foo>).

Example code:

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));
}

I am getting

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

To my best understanding it is due to the fact Google test mock classes are not copyable. I explicitly don't need a copyable mock class. I just need the ability to return list of mocked object. Is it possible in Google test (release-1.8.0)?

One alternative that comes to mind is implement an iterator like patter in Bar, so that it behaves like a vector. However, I want to avoid that approach if possible.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
fahad.shaon
  • 39
  • 1
  • 2
  • 1
    Everything you place in a `vector` must be copy-able because `vector`s do a lot of copying and assigning behind the scenes. For example, `std::vector getFoos()` returns by value which requires the ability to copy, even if the copy is elided. Further, you're walking into [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing) by storing `Foo` and providing a `Foo`-derived class. – user4581301 Jul 20 '18 at 21:53

1 Answers1

0

You need to implement a copy constructor inside your Mockclass, that's how I managed to create a mock class vector. Probably something like this:

MockClass(const MockClass& other) {
    setDefaultBehaviors();   
    defaultId = other.defaultId;
}
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Jeoker
  • 51
  • 12