6

I am currently not succeding in mocking an interface that returns a unique_ptr. For example, given

struct IFoo {     
    virtual std::unique_ptr<IFoo> foo = 0;
};


int main()
{
    MockRepository mocks;
    auto foo = mocks.Mock<IFoo>();
    mocks.OnCall( foo, IFoo::foo )
         .Return( std::unique_ptr<IFoo>() );
}

This fails to compile because the Return implementation makes a copy of the unique_ptr

Call &Return(Y obj) { retVal = new ReturnValueWrapper<Y>(obj); return *this; }

and the expectation attempts to return the unique_ptr

template <typename Z>
Z MockRepository::DoExpectation(base_mock *mock, std::pair<int, int> funcno, const base_tuple &tuple)
{
    ...
    return ((ReturnValueWrapper<Z> *)call->retVal)->rv;
}

I've tried Do, as suggested for a similar problem with returned references.

I've also tried writing my own ValueWrapper<T> that generates a unique_ptr, but somewhere the value always gets copied. Right now I've run out of ideas.

Community
  • 1
  • 1
Thomas
  • 4,980
  • 2
  • 15
  • 30
  • 1
    It seems HippoMocks is not ready for C++11's move-only types yet. Maybe you could write a specialization for `ReturnValueWrapper>` that does *not* copy internally? – Arne Mertz Mar 01 '13 at 14:58
  • Have you tried hippomocks later versions, that have a C++0x version? – Dave S Mar 01 '13 at 16:00
  • @Arne I had more or less tried something like that. Apparently I did something wrong initially. After giving in another go I found a solution that worked. I'll be adding it to the [github repository](https://github.com/dascandy/hippomocks) later. – Thomas Mar 01 '13 at 17:15
  • @Thomas I ran into this exact problem yesterday. Would love to see your changes on Github! – Bret Kuhns Mar 03 '13 at 15:34

1 Answers1

2

One solution to the problem is to create a derived interface with an additional method that returns the return value as a temporary

template <class T>
class TypedReturnValueHolder : public ReturnValueHolder {
public:
    virtual T rv() = 0;
};

and them modifying the original ReturnValueHolder

template <class T>
class ReturnValueWrapper : public ReturnValueHolder {
public:
typename no_cref<T>::type rv;
ReturnValueWrapper(T rv) : rv(rv) {}
};

to inherit from and implement the derived interface.

template <class T>
class ReturnValueWrapper : public TypedReturnValueHolder<T> {
    typename no_cref<T>::type prv;
public:
    ReturnValueWrapper(T rv) : prv(rv) {}
    virtual T rv() { return prv; };
};

Once that has been done, the return from DoExpectation can be written as

        if (call->retVal)
            return ((TypedReturnValueHolder<Z> *)call->retVal)->rv();

The example from the question when rewritten to use Do

mocks.OnCall( foo, IFoo::foo )
     .Do( [](){ return std::unique_ptr<IFoo>(); } );

then compiles and runs as expected.

Thomas
  • 4,980
  • 2
  • 15
  • 30