首页 > 解决方案 > EXPECT_CALL 不满足,但测试通过

问题描述

我正在尝试测试对象的行为,但即使没有调用模拟方法,我的测试也总是通过。

案子很简单。io-blocks很少。每个块都进行数据处理并将它们传递给下一个块。代码如下所示。

GtestCheck.h

#include <memory>
#include <string>

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

using ::testing::NiceMock;
using ::testing::_;
using ::testing::NotNull;
using ::testing::Exactly;

using namespace std::placeholders;

class IoBlock;
typedef std::shared_ptr<IoBlock> IoBlockSharedPtr;

enum class ModuleType : uint8_t
{
    None        =   0x00,
    Type0       =   0x01,
    Type1       =   0x02,
};

class IoBlock
{
    public:
        IoBlock() = delete;
        IoBlock(const IoBlock&) = delete;
        IoBlock(const IoBlock&&) = delete;
        virtual ~IoBlock();

    public:
        IoBlock(const std::string& config);

    public:
        void SetOutputObject(IoBlockSharedPtr outputModule);
        virtual void Input(int x, int y, int z) = 0;

    protected:
        void Output(int x, int y, int z);

    protected:
        ModuleType _moduleType = ModuleType::None;
        std::string _config = "";
        IoBlockSharedPtr _outputBlockPtr;
};


class IoType0 : public IoBlock
{
    public:
        IoType0() = delete;
        IoType0(const IoType0&) = delete;
        IoType0(const IoType0&&) = delete;
        virtual ~IoType0() override;

    public:
        IoType0(const std::string& config) : IoBlock(config) { }

    public:
        virtual void Input(int x, int y, int z) override final;
};


class IoType1mock : public IoBlock
{
    public:
        IoType1mock() = delete;
        IoType1mock(const IoType1mock&) = delete;
        IoType1mock(const IoType1mock&&) = delete;
        virtual ~IoType1mock() override;

    public:
        IoType1mock(const std::string& config);

    public:
        MOCK_METHOD(void, Input, (int x, int y, int z), (override, final));
};

class IoBlockTest : public ::testing::Test
{
    protected:
        void SetUp() override
        {
            _configString = "none0";
            _ioType0block = std::make_shared<IoType0>(_configString);
            _ioType1block = std::make_shared<NiceMock<IoType1mock>>(_configString);

            _ioType1block->SetOutputObject(_ioType0block);
            _ioType0block->SetOutputObject(_ioType1block);

            // gtest reports shared_ptr memory leak
            ::testing::Mock::AllowLeak(_ioType1block.get());
        }

        virtual void TearDown() override { }

        static void SetUpTestCase() { }

        static void TearDownTestCase() { }

    public:
        std::string _configString = "none";
        std::shared_ptr<IoType0> _ioType0block = nullptr;
        std::shared_ptr<NiceMock<IoType1mock>> _ioType1block = nullptr;
};

GtestCheck.cpp

#include "GtestCheck.h"

IoBlock::IoBlock(const std::string& config)
    : _config(config) {}

void IoBlock::SetOutputObject(IoBlockSharedPtr outputModule)
{
    _outputBlockPtr = outputModule;
}

void IoBlock::Output(int x, int y, int z)
{
    if ( _outputBlockPtr != nullptr )
        _outputBlockPtr->Input(x, y, z);
}

IoBlock::~IoBlock() {}

IoType0::~IoType0() {}

IoType1mock::~IoType1mock() {}

void IoType0::Input(int x, int y, int z)
{
    static size_t callCounter = 0;

    if (callCounter++ == 5)
        Output(x, y, z);
}

IoType1mock::IoType1mock(const std::string& config)
    : IoBlock(config) { }

main.cpp

#include <iostream>

#include "GtestCheck.h"

TEST_F(IoBlockTest, SimpleRoute)
{
    //EXPECT_CALL(*_ioType1block, Input(_, _, _)).Times(1);

    EXPECT_CALL(*_ioType1block, Input(_, _, _))
            .Times(1)
            .WillOnce([](int x, int y, int z)
            {
                std::cout << "Input: " << x
                          << " " << y
                          << " " << z << std::endl;
            });

    // Input method trigger code
    //for (size_t i = 0;i < 6; ++i)
    //    _ioType0block->Input(0, 1, 2);
}

int main(int argc, char *argv[])
{
    std::cout << "IoBlockTest unit-tests have been running" << std::endl;
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

当我运行测试时,它通过了。当我取消注释输入法触发线时,它也会通过。

我试图调查这种行为,但没有成功。当我评论那一行时,我只注意到一件事:

_ioType0block->SetOutputObject(_ioType1block);

正如我所料,我的测试失败了。

如果有人知道这种行为的原因,请您描述一下。提前致谢。

测试环境:

操作系统5.10.34-1-MANJARO

测试1.10.0

编译器g++ (10.2.0)

标签: c++unit-testinggoogletest

解决方案


提示在这里:

// gtest reports shared_ptr memory leak
::testing::Mock::AllowLeak(_ioType1block.get());

您的模拟对象泄漏,因此它永远不会被破坏,因此模拟调用的数量永远不会与预期的 1 进行比较。

由于循环依赖关系而发生泄漏。您必须在子级的帮助下std::weak_ptr或在子级中使用std::unique_ptr原始指针而不是std::shared_ptr.


推荐阅读