c++ - 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)
解决方案
提示在这里:
// gtest reports shared_ptr memory leak
::testing::Mock::AllowLeak(_ioType1block.get());
您的模拟对象泄漏,因此它永远不会被破坏,因此模拟调用的数量永远不会与预期的 1 进行比较。
由于循环依赖关系而发生泄漏。您必须在子级的帮助下std::weak_ptr
或在子级中使用std::unique_ptr
原始指针而不是std::shared_ptr
.
推荐阅读
- css - 如何让大图标与 ::marker 中的文本对齐?
- amazon-redshift - SELECT INTO WITH NOT NULL 约束 Redshift
- python - 无法安装 easyocr(pytorch 错误)
- git - 由于主/主更改,我如何更新我的 GitHub 镜像?
- macros - Julia:宏如何知道它们的参数何时停止?
- unit-testing - 编写依赖于同一类中其他函数的单元测试
- html - Django ImageField 模板标签不显示
- python - 如何在 Python 中使用 networkx 计算加权传递性
- java - 如何在 Android 中打开 Kotlin 类 uisng Java 类?
- c# - Asp.net core 继续使用过期的证书