GMock StrictMock uninteresting function call does not fail a test

Viewed 2390

I have come across an incomprehensible behavior using GTest.
The problem is easy. I'm calling sut method. That method calls a StrictMock object method. I don't have any expectation set on that method call. According to the GTest spec, such test should fail because of "uninteresting mock function call". Actually it does not.
Code:

Car.hpp

#pragma once

#include <iostream>
#include <memory>

class EngineIfc;

class Car
{
public:
    Car(const std::shared_ptr<EngineIfc> & engine);

    void start();
    void stop();

private:
    std::shared_ptr<EngineIfc> engine;
};

Car.cpp

#include "Car.hpp"
#include "Engine.hpp"

Car::Car(const std::shared_ptr<EngineIfc> & engine) : engine(engine) {}

void Car::start()
{
    std::cout << "Start Car" << std::endl;
    engine->start();
}

void Car::stop()
{
    std::cout << "Stop Car" << std::endl;
    engine->stop();
}

EngineIfc.hpp

#pragma once

class EngineIfc
{
public:
    virtual ~EngineIfc() = default;
    virtual void start() = 0;
    virtual void stop() = 0;
};

Engine.hpp

#pragma once

#include "EngineIfc.hpp"

class Engine : public EngineIfc
{
public:
    void start() override;
    void stop() override;
};

Engine.cpp

#include "Engine.hpp"

#include <iostream>

void Engine::start()
{
    std::cout << "Start Engine" << std::endl;
}

void Engine::stop()
{
    std::cout << "Stop Engine" << std::endl;
}

EngineMock.hpp

#pragma once

#include "../EngineIfc.hpp"

#include "gmock/gmock.h"

class EngineMock : public EngineIfc
{
public:
    MOCK_METHOD0(start, void());
    MOCK_METHOD0(stop, void());
};

CarTestSuite.cpp

#include "EngineMock.hpp"
#include "../Car.hpp"

#include "gtest/gtest.h"
#include "gmock/gmock.h"

struct CarTestSuite : testing::Test
{
    CarTestSuite() : engine(std::make_shared<EngineMock>()), car(engine)
    {}

    testing::StrictMock<std::shared_ptr<EngineMock>> engine;
    Car car;
};

TEST_F(CarTestSuite, testWhereUnexpectedStrictMockFunctionCallDoesNotFailTheTest)
{
    car.start();
    car.stop();
}

An output from a console:

Running main() from /Users/daniel/Desktop/TimeStamp/GoogleTest/lib/googletest/src/gtest_main.cc
Start Car

GMOCK WARNING:
Uninteresting mock function call - returning directly.
    Function call: start()
NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#knowing-when-to-expect for details.
Stop Car

GMOCK WARNING:
Uninteresting mock function call - returning directly.
    Function call: stop()
NOTE: You can safely ignore the above warning unless this call should not happen.  Do not suppress it by blindly adding an EXPECT_CALL() if you don't mean to enforce the call.  See https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#knowing-when-to-expect for details.

I have tried to change the engine definition and the declaration like this:

struct CarTestSuite : testing::Test
{
    CarTestSuite() : engine(std::make_shared<testing::StrictMock<EngineMock>>()), car(engine)
    {}

    std::shared_ptr<testing::StrictMock<EngineMock>> engine;
    Car car;
};

after that the test fails as it should.
The question is: why?
Please help me to understand.

Thanks in advance.

1 Answers

I think this is due to the fact that StrictMock (as well as NiceMock and NaggyMock, the default one) are template classes looking like that:

template <class MockClass>
class StrictMock : public MockClass
[...]

so in testing::StrictMock<std::shared_ptr<EngineMock>> case, the base class for the StrictMock is shared_ptr<EngineMock>, not EngineMock itself. As per comment in the source file: A known limitation is that NiceMock<MockFoo>, NaggyMock<MockFoo>, and StrictMock<MockFoo> only works for mock methods defined using the MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.

So in this case is not DIRECTLY in the MockFoo class I think - hence it might not work.

Related