【问题标题】:GMOCK EXPECT_CALL on unique_ptrunique_ptr 上的 GMOCK EXPECT_CALL
【发布时间】:2018-12-30 14:41:50
【问题描述】:

依赖注入的好处之一是易于测试,因为可以注入模拟类。 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-&gt;doSth() 正在调用应该返回 100 的 injectedObj-&gt;executeSth,但它的行为就像我永远不会设定我的期望并且总是得到 0。显然,如果我在没有智能指针的情况下调用我的模拟对象:@987654329 @ 它返回 100,但在使用 unique_ptr 调用它时不返回。当模拟对象由智能指针管理时,有什么方法可以告诉 gmock 设置正确的期望?谢谢

【问题讨论】:

  • 我不太明白您要做什么:1. Clazz::Clazz() 采用原始指针并将其存储到 std::unique_ptr&lt;&gt;; 2.std::shared_ptr&lt;Clazz&gt; clazz(injectedObj);直接将原始指针传递给std::shared_ptr&lt;&gt;
  • 是的,Clazz 使用原始指针来启用模拟依赖注入,并将其存储为它拥有的唯一指针。 2. 我还将 Clazz 作为 shared_ptr 来处理清理工作。所以基本上我不想对注入的模拟设定期望,它在 Clazz 构造函数中变成了 unique_ptr。
  • 还是不明白。请提供Minimal, Complete, and Verifiable example
  • 我也有同样的问题,问题指出要找到一种方法来测试/模拟对象的 shared_ptr。在我的情况下, shared_ptr 是 Clazz 的,它是 Claz 主要对象的模拟。为这个问题添加书签,我遇到了同样的问题。
  • Clazz 中有 operator-&gt; 吗?它返回什么?

标签: c++11 gmock


【解决方案1】:

给定:

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)

我敢打赌:你忘了在InjectedObj 的基类中标记executeSth 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)

避免这种情况的最佳方法:始终将基类设为纯虚拟 iface。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-25
    • 2022-08-10
    • 1970-01-01
    • 2022-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多