如何为刚刚创建的模拟对象设置 EXPECT_CALL?

问题描述 投票:0回答:1

这是我的测试情况。 googletest 中有一条注释,必须在调用模拟方法之前先设置 EXPECT_CALL (https://google.github.io/googletest/gmock_for_dummies.html#expectation-ordering)。我的问题是我有一个模拟对象,只会稍后初始化。在初始化之后,将立即调用模拟对象的模拟方法。 这样,因为我无法在尚不存在的模拟对象上设置 EXPECT_CALL。我被迫在创建模拟对象时及时设置 EXPECT_CALL 。现在我的测试中发生的情况是模拟方法调用首先发生在 EXPECT_CALL 之前。由于该序列,我的测试失败了,因为它没有捕获 EXPECT_CALL 中预期的模拟方法。 这是伪代码:

在代码中我正在测试。

Client client = new Client();
// some actions with client…
// Later on Document object is created…
std::unique<Document> doc = client->CreateDocument();
if (doc->Process())
{
….

在谷歌测试中。

TEST_F(ClientTesting, CanProcess)
{
… expect calls on client …
// Only being able to add expect call here because before this, document object is not yet created.
EXPECT_CALL(*mockDoc, Process).WillOnce(Return(true));
}

测试表明,在 Document 对象的 Process 方法上有一个无趣的模拟方法调用。那么它就会失败,说期望调用 Document 对象的 Process 方法,但没有调用。我相信这是因为模拟方法在单元测试中的 EXPECT_CALL 之前首先在被测代码中被调用。

我尝试在创建

sleep()
对象后添加一些
Document
,以查看对其进行的模拟方法调用是否会被 EXCEPT_CALL 捕获。

Client client = new Client();
// some actions with client…
// Later on Document object is created…
std::unique<Document> doc = client->CreateDocument();
sleep(2);
if (doc->Process())
{
….
c++ unit-testing mocking tdd googletest
1个回答
0
投票

最简单的解决方案:将

EXPECT_CALL
放入模拟的构造函数中: https://godbolt.org/z/5YhfP9K6x

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

using namespace testing;

struct Doc
{
    Doc() 
    { EXPECT_CALL(*this, process).WillOnce(Return(true)); }
    MOCK_METHOD(bool, process,());
};

auto f()
{
    return std::make_unique<Doc>();
}

bool g()
{
    return f()->process();
}

TEST(a,b)
{
    EXPECT_TRUE(g());
}

或者为了获得更多控制,您可以将其包装在一个控制其返回值的类中: https://godbolt.org/z/5q8e6e846

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

using namespace testing;

struct IDoc
{
    virtual bool process() = 0;
    virtual ~IDoc() = default;
};

struct DocMock : IDoc
{
    MOCK_METHOD(bool, process,(), (override));
};

struct DocWrap : IDoc
{
    static inline bool retval = false;

    bool process() override
    {
        EXPECT_CALL(mock, process).WillOnce(Return(retval));
        return mock.process();
    }
    DocMock mock{};
};

std::unique_ptr<IDoc> f()
{
    return std::make_unique<DocWrap>();
}

bool g()
{
    return f()->process();
}

TEST(a,b)
{
    DocWrap::retval=false;
    EXPECT_FALSE(g());
}

如果通过静态变量处理它是一个好主意那就是另一个故事了。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.