【发布时间】:2021-06-21 03:52:20
【问题描述】:
我正在尝试模拟成员方法parseString,以便:
- 保持原来的行为,即返回原来的方法返回值作为原来的方法填充输出参数(
std::vector<std::string>& iReqs); - 我可以检查其输出参数之一 (
std::vector<std::string>& iReqs)
可能有一种简单的方法可以做到这一点,但到目前为止我还没有找到一种干净的方法。 我最接近的是以下内容,使用 GMock:
- 使用 lambda 来模仿原始方法的行为
- 使用
SaveArgs存储参数
这种方法的问题是SaveArgs 不返回任何值,并且它使测试在发布模式下编译崩溃。如果我反转两个DoAll 语句,SaveArgs 在方法实际填充它之前被调用,所以它没有意义。如果我添加步骤 3. 并稍微修改步骤 1.:
- 使用 lambda 来模仿原始方法行为并存储原始返回值;
- 使用
SaveArgs存储参数; - 返回原来的返回值;
然后它似乎可以工作,除了我的测试中的一种情况,所以看起来可能有一些未定义的行为隐藏在这个解决方案.
代码sn-p:
class FooMock : public Foo
{
public:
FooMock() : Foo()
{
// By default, all calls are delegated to the real object.
// Moreover, we capture intermediary object for testing purposes
// We need to save _originalReturn otherwise we will have undef behaviour
ON_CALL(*this, parseString).WillByDefault(DoAll(
([this](const std::string& iDoc,
std::vector<std::string>& iReqs) {
_originalReturn = this->Foo::parseString(iDoc, iReqs);
return _originalReturn;
}),
SaveArg<1>(&_requests),
Return(_originalReturn)
));
}
MOCK_METHOD2(parseString, bool (const std::string& iDoc,
std::vector<std::string>& iReqs));
virtual ~FooMock() = default;
std::vector<std::string> _requests;
private:
bool _originalReturn = false;
};
class Foo
{
public:
Foo() = default;
virtual ~Foo() = default;
bool execute( const std::string& iMessage ) {
// Calling parseString here
return true;
}
protected:
virtual bool parseString(const std::string& iMessage,
std::vector<std::string>& oBom){
//Does something here
return true;
}
};
在 GTest 中,我应该能够做到以下几点:
TEST_F( FooMockTest, basicRequest )
{
std::string aString = "Something";
FooMock uc;
EXPECT_CALL(uc, parseString(_, _)).Times(1);
EXPECT_TRUE(uc.execute(aString));
// Test some property of the output parameter...
ASSERT_EQ(1U, uc._requests.size());
}
同样,我无法找到一种方法来连接我希望模拟的成员方法的两种行为,即保留其原始行为并在其原始执行后保存 args。
我认为我最新的 sn-p 不安全,可能会隐藏一些不一致(因为我通过一个中间变量作为 Mocked 类成员字段)。
你能帮忙吗?谢谢!
【问题讨论】:
-
我想帮忙,但由于 sn-p 不是minimal reproducible example,我不想花时间解决编译器错误。特别是 { 没有匹配的标记,Boo 和 b 未定义,缺少包含的标头和使用指令...
-
@S.M.感谢您的反馈意见。我更新了快照以使其具有连贯性,对不精确表示抱歉。顺便说一句,sn-p 应该编译(这不是编译问题,而是运行时问题)。这个问题并不完全清楚,我同意,我试图改进它。
-
我认为你误解了mock对象和gmock的用法:
FooMock可以用来代替Foo进行测试但不能自己测试,ON_CALL似乎被调用了测试用例。
标签: c++ unit-testing googletest gmock