单元测试——如何使用Google Test来测试一个函数,该函数将调用包含输出参数的另一个函数


// Filter.h/cpp
class Filter
{
public:
    int readInt(int* value)
    {
        if (value == NULL)
            return 0;
        *value = 15; // some logical;
        return 1;
    }
};

// TestTee.h/.cpp
class TestTee
{
public:
  Func1(Filter* f)
  {
      ...
      int val;
      f->readInt(&val);
      ...
  }
}

现在,我需要测试TestTee类,所以我模拟类Filter

class MockFilter : public Filter
{
public:
    MOCK_METHOD1(readInt, int(int*));
};

如何编写测试用例?

TEST_F(TestClass, Test1)
{
    TestTee t;
    MockFilter filter;
    EXPECT_CALL(filter, readInt(_)).Times(1);  //  failed error:     The mock function has no default action set, and its return type has no default value set." thrown in the test body.
    /* 
    int val;
    EXPECT_CALL(filter, readInt(&val)).Times(1); 
    Failed with the following error:
          Expected: to be called once
          Actual: never called - unsatisfied and active
    */
    t.Func1(&filter);
}

我的问题是

我不知道如何控制将在我的测试函数代码中调用的函数的输出参数。

何评论?非常感谢。

首先,不要忘记函数需要是虚拟的,以便GoogleMock能够真正模拟它:

class Filter
{
public:
    virtual int readInt(int* value)
    {
        if (value == NULL)
            return 0;
        *value = 15; // some logical;
        return 1;
    }
};

测试代码取决于您实际想要测试的内容。如果你只是想确保Filter::readInt被调用,这应该足够了:

TEST_F(TestClass, Test1)
{
    TestTee t;
    MockFilter filter;
    EXPECT_CALL(filter, readInt(_));
    t.Func1(&filter);
}

(因为readInt有内置的返回类型(int) GoogleMock应该能够找出默认的返回值而没有抱怨)

如果你想确保readInt只被调用一次,使用Times子句:

EXPECT_CALL(filter, readInt(_)).Times(1);

如果你想在readInt调用之后的Testee代码在测试期间获得足够的返回值,也就是说,如果你想模拟真实函数的返回值,使用return子句作为返回值,使用SetArgPointee子句作为指针传递的输出值,或者两者都像这样:

EXPECT_CALL(filter, readInt(_)).WillOnce(DoAll(SetArgPointee<0>(15), Return(1)));

最新更新