简体   繁体   中英

Using googlemock EXPECT_CALL with shared_ptr?

I have a test that works fine with a raw pointer, but I'm having trouble getting it work with a std::shared_ptr . The class is like this:

class MyClass
{
    MyClass(SomeService *service);
    void DoIt();
}

My test code is like:

    class MyClassTests : public ::testing::Test
    {
    public:
        MyClassTests():
            myClass_(new MyClass(&service_))
        {}

    protected:
        SomeServiceFake service_;
        MyClassSharedPointer myClass_;
    };

TEST_F(MyClassTests, DoIt_DoesNotMeetCriteria_DoesNotPerformAction) {

    // Arrange
    EXPECT_CALL(service_, MeetsCriteria(_))
        .WillRepeatedly(Return(false));

    EXPECT_CALL(service_, PerformAction(_))
        .Times(0);

    // Act
    myClass_->DoIt();
}

In this test, service_ is a mock/fake created on the stack in the test and I pass the address into the constructor of MyClass . Changing MyClass to take service as a shared_ptr , my new class looks like:

class MyClass
{
    MyClass(std::shared_ptr<SomeService> service);
    DoIt();
}

What I'm trying in my test is:

    class MyClassTests : public ::testing::Test
    {
    public:
        MyClassTests():
            myClass_(new MyClass(std::shared_ptr<SomeService>(&service_)))
        {

        }
            ...

When I do this, however, the test fails with a:

Debug Assertion Failed!
Expression: _CtrlIsValidHeapPointer(pUserData)

In a nutshell, I need a shared_ptr to service_ (which is a fake object) to pass to the MyClass constructor and I need a non-pointer for the EXPECT_CALL function. How can I get this to work correctly?

UPDATE

Tried dynamically allocating SomeServiceFake to get the shared_ptr and then using the * operator on service_ , this gets me "further" but now I get the following error:

error : this mock object
(used in test MyClassTests.DoIt_DoesNotMeetCriteria_DoesNotPerformAction)
should be deleted but never is. Its address is @009BBA68.
1>EXEC : error : 1 leaked mock object found at program exit.

UPDATE 2

Using Mock::AllowLeak(service_.get()); so I can get around this problem for now. Hopefully I'll get an answer.

Define your test class more like this:

class MyClassTests : public ::testing::Test {
 public:
  MyClassTests():
      service_(new SomeServiceFake), myClass_(new MyClass(service_)) {}
 protected:
  std::shared_ptr<SomeServiceFake> service_;
  std::shared_ptr<MyClass> myClass_;
};

and your test:

  EXPECT_CALL(*service_, MeetsCriteria(_))
      .WillRepeatedly(Return(false));

  EXPECT_CALL(*service_, PerformAction(_))
      .Times(0);

This has nothing to do with the test framework. As you said yourself, you are creating a shared_ptr from a stack-allocated object (ie one with automatic lifetime). This does not make sense. Shared pointers are typically created from the result of new . You might be able to make it work if you pass a custom Deleter as the second argument to the shared_ptr constructor, but best might be to just create the object using new.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM