문제

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?

도움이 되었습니까?

해결책

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top