在unique_ptr上进行GMOCK EXPECT_CALL

时间:2018-07-23 07:43:00

标签: c++11 gmock

依赖注入的好处之一是易于测试,因为可以注入模拟类。 Clazz为此使用原始指针,并将其移动到唯一指针,以表示它拥有InjectedObj对象:

Clazz::Clazz(InjectedObj *injectedObj)  : injectedObjPtr(injectedObj) { }

其中injectedObjPtr是成员:

std::unique_ptr<InjectedObj> injectedObjPtr;

doSth方法通过调用智能指针来调用executeSth:

//doSth method
int CLazz::doSth() {
return injectedObjPtr->executeSth();
}

我想通过对注入对象设置一些期望来测试Clazz, 所以我的测试看起来与此类似:

TEST_F(testFixture, exeuteTest)
{
  //before
  InjectedObj* injectedObj = new InjectedObj();
  EXPECT_CALL(*injectedObj, executeSth())
    .Times(1)
    .WillOnce(Return(100));

  //when
  Clazz clazz(injectedObj);

  //then
  ASSERT_DOUBLE_EQ(clazz->doSth(), 100);
}

因此,在这种简化的情况下,clazz->doSth()正在调用injectedObj->executeSth,它应返回100,但其行为就像我永远不会设置期望值并始终为0。指针:injectedObj->executeSth返回100,但使用unique_ptr调用时不会返回。当模拟指针由智能指针管理时,是否有任何方法告诉gmock设置正确的期望值?谢谢

1 个答案:

答案 0 :(得分:0)

给定:

struct InjectedObj {
    MOCK_METHOD0(executeSth, int());
};

struct Clazz {
    Clazz(InjectedObj* injectedObj)
            : injectedObjPtr(injectedObj) {}

    int doSth() {
        return injectedObjPtr->executeSth();
    }

    std::unique_ptr<InjectedObj> injectedObjPtr;
};

TEST(testFixture, exeuteTest) {
    // before
    InjectedObj* injectedObj = new InjectedObj();
    EXPECT_CALL(*injectedObj, executeSth()).Times(1).WillOnce(testing::Return(100));

    // when
    Clazz clazz(injectedObj);

    // then
    ASSERT_DOUBLE_EQ(clazz.doSth(), 100);
}

我得到了:

[----------] 1 test from testFixture
[ RUN      ] testFixture.exeuteTest
[       OK ] testFixture.exeuteTest (0 ms)
[----------] 1 test from testFixture (0 ms total)

我敢打赌:您忘记在基类中为 executeSth 标记 InjectedObj 一个 virtual 方法。这样,gmock 生成的 gmock_executeSth 方法是您设置的期望值,但在测试 executeSth 中使用了基类(没有动态分派),因此测试失败。

// Example, bad
// THE executeSth METHOD SHALL BE MARKED WITH virtual!!!!!
struct InjectedObj {
    virtual ~InjectedObj() = default;
    int executeSth() {
        return 0;
    }
};

struct InjectedObjMock : public InjectedObj {
    MOCK_METHOD0(executeSth, int());
};

struct Clazz {
    Clazz(InjectedObj* injectedObj)
            : injectedObjPtr(injectedObj) {}

    int doSth() {
        return injectedObjPtr->executeSth();
    }

    std::unique_ptr<InjectedObj> injectedObjPtr;
};

TEST(testFixture, exeuteTest) {
    // before
    InjectedObjMock* injectedObj = new InjectedObjMock();
    EXPECT_CALL(*injectedObj, executeSth()).Times(1).WillOnce(testing::Return(100));

    // when
    Clazz clazz(injectedObj);

    // then
    ASSERT_DOUBLE_EQ(clazz.doSth(), 100);
}

输出:

[ RUN      ] testFixture.exeuteTest
/home/dchrzanowski/gitrepos/priv/gtestgmock/so.cpp:41: Failure
      Expected: clazz.doSth()
      Which is: 0
To be equal to: 100
/home/dchrzanowski/gitrepos/priv/gtestgmock/so.cpp:35: Failure
Actual function call count doesn't match EXPECT_CALL(*injectedObj, executeSth())...
         Expected: to be called once
           Actual: never called - unsatisfied and active
[  FAILED  ] testFixture.exeuteTest (0 ms)
[----------] 1 test from testFixture (0 ms total)

避免这种情况的最佳方法:始终使基类成为纯虚拟接口。