Googletest: Workaround to use ByMove in SaveArg?

Created on 19 Sep 2019  Â·  3Comments  Â·  Source: google/googletest

I´m aware that the ByMove is available for returning from mocked classes, but what about setting one parameter (by using SaveArg or something) of a mocked function that accepts std::unique_ptr? I have the following code:

class MockCustomBuffer : public CustomBuffer {
public:
    MOCK_METHOD1(insert, void(std::unique_ptr<CustomData>));
    MOCK_METHOD0(get, std::unique_ptr<CustomData>());
};

class MyTest : public testing::Test {
public:
    unique_ptr<CustomBuffer> mockCustomBuffer = make_unique<MockCustomBuffer>();  
    MockCustomBuffer * mockCustomBufferPtr = static_cast<MockCustomBuffer*>(mockCustomBuffer.get());

    unique_ptr<MyTestableClass> subject;
    MyTest () {
        subject = make_unique<MyTestableClass>(move(mockCustomBuffer));
    }
};

TEST_F(CustomBufferTest, TestOne) {
  auto dataPtr = make_unique<CustomData>();
  EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce(SaveArg<0>( move(dataPtr) ));
  auto dataPtr2 = make_unique<CustomData>();
 subject->populate(move(dataPtr2));
}

It fails on the part of EXPECT_CALL(*mockCustomBufferPtr, ...); with the error: error: call to deleted constructor of 'std::unique_ptr<CustomData, std::default_delete<CustomData> >'. I also have tried using ByMove, but also without success.

Any hints?

Most helpful comment

On Thu, Sep 19, 2019 at 12:54 PM Giseli notifications@github.com wrote:

I´m aware that the ByMove is available for returning from mocked classes,
but what about setting one parameter (by using SaveArg or something) of a
mocked function that accepts std::unique_ptr? I have the following code:

class MockCustomBuffer : public CustomBuffer {

public:

MOCK_METHOD1(insert, void(std::unique_ptr<CustomData>));

MOCK_METHOD0(get, std::unique_ptr<CustomData>());

};

class MyTest : public testing::Test {

public:

unique_ptr<CustomBuffer> mockCustomBuffer = make_unique<MockCustomBuffer>();



MockCustomBuffer * mockCustomBufferPtr = static_cast<MockCustomBuffer*>(mockCustomBuffer.get());



unique_ptr<MyTestableClass> subject;



MyTest () {

    subject = make_unique<MyTestableClass>(move(mockCustomBuffer));

}

};

TEST_F(CustomBufferTest, TestOne) {

auto dataPtr = make_unique();

EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce(SaveArg<0>( move(bufferPtr) ));

auto dataPtr2 = make_unique();

subject->populate(move(dataPtr2));

}

It fails on the part of EXPECT_CALL(*mockCustomBufferPtr, ...); with the
error: error: call to deleted constructor of 'std::unique_ptr std::default_delete >'. I also have tried using ByMove, but
also without success.

tl;dr: if builtin actions don't do what you need, use a custom lambda
instead.
Eg:
EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce(& {
destination = std::move(arg0); });

ByMove is a workaround that only really works for the Return action, and it
was added before we had intrinsic support for callables.
Nowadays we suggest using a lambda when it would otherwise be too hard to
do with regular actions. It is too much noise to retrofit move semantics on
all actions in a way that works consistently.

Any hints?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/google/googletest/issues/2464?email_source=notifications&email_token=ADLRCPM6BRL33QJOE7U5WKDQKOVDVA5CNFSM4IYNUKOKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HMPC4NA,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADLRCPI3IUGZK5NBTPVOLITQKOVDVANCNFSM4IYNUKOA
.

All 3 comments

On Thu, Sep 19, 2019 at 12:54 PM Giseli notifications@github.com wrote:

I´m aware that the ByMove is available for returning from mocked classes,
but what about setting one parameter (by using SaveArg or something) of a
mocked function that accepts std::unique_ptr? I have the following code:

class MockCustomBuffer : public CustomBuffer {

public:

MOCK_METHOD1(insert, void(std::unique_ptr<CustomData>));

MOCK_METHOD0(get, std::unique_ptr<CustomData>());

};

class MyTest : public testing::Test {

public:

unique_ptr<CustomBuffer> mockCustomBuffer = make_unique<MockCustomBuffer>();



MockCustomBuffer * mockCustomBufferPtr = static_cast<MockCustomBuffer*>(mockCustomBuffer.get());



unique_ptr<MyTestableClass> subject;



MyTest () {

    subject = make_unique<MyTestableClass>(move(mockCustomBuffer));

}

};

TEST_F(CustomBufferTest, TestOne) {

auto dataPtr = make_unique();

EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce(SaveArg<0>( move(bufferPtr) ));

auto dataPtr2 = make_unique();

subject->populate(move(dataPtr2));

}

It fails on the part of EXPECT_CALL(*mockCustomBufferPtr, ...); with the
error: error: call to deleted constructor of 'std::unique_ptr std::default_delete >'. I also have tried using ByMove, but
also without success.

tl;dr: if builtin actions don't do what you need, use a custom lambda
instead.
Eg:
EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce(& {
destination = std::move(arg0); });

ByMove is a workaround that only really works for the Return action, and it
was added before we had intrinsic support for callables.
Nowadays we suggest using a lambda when it would otherwise be too hard to
do with regular actions. It is too much noise to retrofit move semantics on
all actions in a way that works consistently.

Any hints?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/google/googletest/issues/2464?email_source=notifications&email_token=ADLRCPM6BRL33QJOE7U5WKDQKOVDVA5CNFSM4IYNUKOKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HMPC4NA,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADLRCPI3IUGZK5NBTPVOLITQKOVDVANCNFSM4IYNUKOA
.

About the lambda, do you mean by using:

EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce([&](auto& arg0) {
dataPtr = std::move(arg0); });

?
It still fails, with the following: no viable conversion from 'lambda at local/of/test/code´ to 'const Action<void (std::unique_ptr<CustomData, std::default_delete<CustomData> >)>'

Okay, got it working by using:

  auto dataPtr = make_unique<CustomData>();
  EXPECT_CALL(*mockCustomBufferPtr, insert(_)).WillOnce([&dataPtr](std::unique_ptr<CustomData> arg0) { dataPtr = std::move(arg0); });

The use of the auto& was not helping the lambda to deduct the type, so I explicity set the type.
Thanks for the help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

agirault picture agirault  Â·  5Comments

Joebeazelman picture Joebeazelman  Â·  5Comments

kuzkry picture kuzkry  Â·  6Comments

nholthaus picture nholthaus  Â·  6Comments

ElectricRCAircraftGuy picture ElectricRCAircraftGuy  Â·  4Comments