Question

I have a problem with one of my googletest unittests that uses a mock object and a death test. This is a minimized code sample that illustrates the problem:

#include <gtest/gtest.h>
#include <gmock/gmock.h>

using namespace ::testing;

class MockA {
  public:
    MockA() {};
    virtual ~MockA() {};

    MOCK_METHOD1(bla,int(int));
};


class B {
  public:
    B(MockA * a)
            : a_(a) {};
    void kill() {
        exit(1);
    }
    MockA * a_;
};

TEST(BDeathTest,BDies) {
    MockA * a = new MockA();
    ON_CALL(*a,bla(_)).WillByDefault(Return(1));
    B * b = new B(a);
    EXPECT_DEATH(b->kill(),"");
    delete a;
}

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

The output:

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from BDeathTest
[ RUN      ] BDeathTest.BDies

gtest.cc:27: ERROR: this mock object (used in test BDeathTest.BDies) should be deleted but never is. Its address is @0x7fe453c00ec0.
ERROR: 1 leaked mock object found at program exit.
[       OK ] BDeathTest.BDies (2 ms)
[----------] 1 test from BDeathTest (2 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (2 ms total)
[  PASSED  ] 1 test.

It seems like googlemock checks for left over mock objects on the heap right after the EXPECT_DEATH assertion, but deleting a before invoking the macro is obviously not a good solution, as a might be used in the function that's invoked. I would actually expect the check to occur at the end of the test suite deconstruction. What am I missing?

Was it helpful?

Solution

Since a will be leaked, you need to tell gmock about this:

TEST(BDeathTest,BDies) {
    MockA * a = new MockA;
    ON_CALL(*a,bla(_)).WillByDefault(Return(1));
    B * b = new B(a);
    Mock::AllowLeak(a);  // <=== Self-explanatory addition
    EXPECT_DEATH(b->kill(),"");
    delete a;
    delete b;
}


You can also use ::testing::FLAGS_gmock_catch_leaked_mocks = false; to switch off all gmock leak detection, but this is probably a bad habit to get into. It may be appropriate in this case however if you have a large number of mock objects when you call exit(). It's also worth switching it back on immediately after EXPECT_DEATH in case the test goes on to do further work (although in your example above, it's pointless to switch it back on).

TEST(BDeathTest,BDies) {
    MockA * a = new MockA;
    ON_CALL(*a,bla(_)).WillByDefault(Return(1));
    B * b = new B(a);
    FLAGS_gmock_catch_leaked_mocks = false;  // <=== Switch off mock leak checking
    EXPECT_DEATH(b->kill(),"");
    FLAGS_gmock_catch_leaked_mocks = true;  // <=== Re-enable mock leak checking
                                            //      in case the test is refactored
    delete a;
    delete b;
}


Finally, a third way to handle this particular case is to delete a_; in B::kill() rather than allowing it to leak.

class B {
    ...
    void kill() {
        delete a_;
        exit(1);
    }
    MockA * a_;
};

TEST(BDeathTest,BDies) {
    MockA * a = new MockA;
    ON_CALL(*a,bla(_)).WillByDefault(Return(1));
    B * b = new B(a);
    EXPECT_DEATH(b->kill(),"");
    delete a;
    delete b;
}

Since gtest spawns a new process to execute the death test, you're safe to delete a_ just before exiting while also deleting a inside the test fixture.

However, to someone who doesn't know how gtest death tests work, this would look like the same variable getting deleted twice, and could cause confusion.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top