Googlemock неправильно сообщает об ошибке при выходе из теста.Что я делаю неправильно? - PullRequest
3 голосов
/ 08 декабря 2011

Googlemock неправильно сообщает о проблеме при выходе из теста. Что я делаю неправильно? Я изучил документацию по googlemock, но нет хорошего полного примера и ничего, описывающего мою проблему.

Я получаю ошибку:

googlemocktest.cpp(53): ERROR: this mock object should be deleted but never is.
Its address is @0018FDC4.
ERROR: 1 leaked mock object found at program exit.

Код для простого теста:

#include <string>
#include <iostream>
#include <memory>
#include "gmock/gmock.h"

class IBar
{
public:
    virtual ~IBar() {}
    virtual void b() = 0;
    virtual int c(std::string) = 0;
};

class Foo
{
private:
    IBar *bar_;
public:
    Foo(IBar *bar);
    int a();
};

Foo::Foo(IBar *bar)
    : bar_(bar)
{
}

int Foo::a()
{
//  bar_->b();
    return bar_->c("hello");
}

class BarMock : public IBar
{
public:
    MOCK_METHOD0(b, void());
    MOCK_METHOD1(c, int(std::string));
};

using ::testing::Return;

void TestAFunctionInFoo()
{
    try
    {
        BarMock barMock;
        std::unique_ptr<Foo> newFoo(new Foo(&barMock));

        EXPECT_CALL(barMock, b());
        EXPECT_CALL(barMock, c("hello")).WillOnce(Return(42));

        newFoo->a();
    }
    catch (std::exception& e)
    {
        std::cout << "Mock exception caught: " << e.what() << std::endl;
    }
    catch (...)
    {
    }
}

int main(int argc, char* argv[])
{
    ::testing::GTEST_FLAG(throw_on_failure) = true;
    ::testing::InitGoogleMock(&argc, &argv[0]);
    TestAFunctionInFoo();
    return 0;
}

Я подтвердил с помощью отладчика, что IBar :: ~ IBar () действительно вызывается. Но я все еще получаю это сообщение об ошибке. Если я раскомментирую вызов IBar :: b () в Foo :: a (), то теста не будет, поэтому оператор catch не будет вызван. IBar :: ~ IBar () вызывается, но нет сообщения об ошибке, указывающего, что фиктивный объект не удален.

Большое спасибо за вашу помощь!

1 Ответ

4 голосов
/ 11 января 2012

Это происходит потому, что вы включили флаг throw_on_failure - как уже упоминалось в Google Mock ForDummies :

Этот подход имеет подвох: он заставляет Google Mock выдавать исключениеиногда из деструктора фиктивного объекта.

Так как из деструктора выбрасывается исключение, фиктивный объект никогда не удаляется полностью, и фреймворк жалуется на это, когда программа заканчивается.

Самое простое решение этой проблемы - использовать Google Test в качестве основы для модульного тестирования и отключить флаг throw_on_failure (состояние по умолчанию) - GTest автоматически не проходит тест, если фиктивные ожидания не удовлетворяются в пределах.

Если вы не можете использовать Google Test, потому что вы используете другую платформу (например, CppUnit), вы можете переписать ваше тело теста следующим образом:

void TestAFunctionInFoo()
{
    ::testing::GTEST_FLAG(throw_on_failure) = true;
    BarMock barMock;

    try
    {
        std::unique_ptr<Foo> newFoo(new Foo(&barMock));

        EXPECT_CALL(barMock, b());
        EXPECT_CALL(barMock, c("hello")).WillOnce(Return(42));

        newFoo->a();
        ::testing::Mock::VerifyAndClearExpectations(&barMock);
    }
    catch (std::exception& e)
    {
        // expectations failed - do whatever you want 
    }

    ::testing::GTEST_FLAG(throw_on_failure) = false;
}

VerifyAndClearExpectations(void*) проверяет, удовлетворены ли данные ложные ожидания - если нет, иФлаг throw_on_failure включен, он выдает исключение.

Таким образом, ваш фиктивный объект будет уничтожен должным образом, и у вас все равно будет исключение, если что-то пошло не так.

Кстати: избегайте использованияcatch (...) { } - это вообще плохая идея, которая в большинстве случаев доказывает плохое качество кода.

...