GoogleMock,返回参数和正常返回,使用数组

时间:2018-03-28 15:20:55

标签: c++ googletest googlemock

我正在嘲笑一个用于读取串行数据的低级接口。该接口具有公共函数,用于从其内部缓冲区读取字节。我想模拟这个接口,所以我可以返回一个字节序列,并且对于返回的每个字节也返回值true。一旦超出要读取的字节数,该函数必须返回false

我现在正在做的事情如下:

struct IUart
{
    virtual bool Read(uint8_t& value) = 0;
    //... other functions
};

struct MockUart: IUart
{
    MOCK_METHOD1(Read, bool(uint8_t&));
    //... other functions
};

struct TestMyTest: ::testing::Test
{
    /* Setting up test fixture */
};

TEST_F(TestMyTest, TestMyMockedInterface)
{
    MockUart uartMock;

    EXPECT_CALL(uartMock, Read(::testing::_))
        .WillOnce(::testing::DoAll(::testing::SetArgReferee<0>(10), ::testing::Return(true)))
        .WillOnce(::testing::DoAll(::testing::SetArgReferee<0>(11), ::testing::Return(true)))
        .WillOnce(::testing::DoAll(::testing::SetArgReferee<0>(12), ::testing::Return(true)))
        .WillOnce(::testing::Return(false));

    //... etc
}

还有其他方法可以促进这一点吗?是否有一些::testing::WithNextValueFromArray选项可供选择?

1 个答案:

答案 0 :(得分:1)

没有什么比你所描述的更好,而且#34;开箱即用&#34;在谷歌模拟,但你可以编写自己的行动来实现这一目标。但是,有几种方法可以解决这个问题:

选项1

编写一个几乎完全符合您所描述的操作:

{{2然后按如下方式使用它:

ACTION_TEMPLATE(SetArgWithNextValueFromArray,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_1_VALUE_PARAMS(results))
{
    ::testing::get<k>(args) = results->front();
    results->erase(results->begin());
}

此操作具有可以与其他测试重用的优点,但它仍然有些冗长。

< h1>选项2

编写一个从UART成功模拟阅读的操作:

TEST_F(TestMyTest, TestMyMockedInterface)
{
    MockUart uartMock;
    std::vector<uint8_t> results = { 10, 11, 12 };

    EXPECT_CALL(uartMock, Read(::testing::_))
        .WillOnce(::testing::DoAll(SetArgWithNextValueFromArray<0>(&results),::testing::Return(true)))
        .WillOnce(::testing::DoAll(SetArgWithNextValueFromArray<0>(&results),::testing::Return(true)))
        .WillOnce(::testing::DoAll(SetArgWithNextValueFromArray<0>(&results),::testing::Return(true)))
        .WillOnce(::testing::Return(false));
}

然后按如下方式使用它:

ACTION_P(ReadSuccessfully, results)
{
    arg0 = results->front();
    results->erase(results->begin());
    return true;
}
< p>此操作的可重用性较低,但不太详细。

选项3

编写一个模拟UART读取的操作:

TEST_F(TestMyTest, TestMyMockedInterface)
{
    MockUart uartMock;
    std::vector<uint8_t> results = { 10, 11, 12 };

    EXPECT_CALL(uartMock, Read(::testing::_))
        .WillOnce(ReadSuccessfully(&results))
        .WillOnce(ReadSuccessfully(&results))
        .WillOnce(ReadSuccessfully(&results))
        .WillOnce(::testing::Return(false));
}

然后按如下方式使用它:

ACTION_P(FakeRead, results)
{
    if (results->empty())
    {
        return false;
    }
    arg0 = results->front();
    results->erase(results->begin());
    return true;
}

此操作也不是非常可重用,但是最不详细。该操作具有TEST_F(TestMyTest, TestMyMockedInterface) { MockUart uartMock; std::vector<uint8_t> results = { 10, 11, 12 }; EXPECT_CALL(uartMock, Read(::testing::_)).WillRepeatedly(FakeRead(&results)); } 的完整虚假实现,这对于您的某些测试非常有用。另一方面,一个完整的假实现本身可能是错误的,这可能会对您的测试产生负面影响。

可能还有其他选择,但这些应该可以提供足够的实例来说明。