Using googlemock EXPECT_CALL with shared_ptr?

User picture User · Apr 26, 2012 · Viewed 17.3k times · Source

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.

Answer

Fraser picture Fraser · Apr 27, 2012

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