Col*_*nic 6 c++ unit-testing mocking googlemock
当您需要调用真实对象的功能时,Google 建议将调用委托给父对象,但这并不会真正创建部分(混合)模拟。调用真实对象时,任何方法调用都是真实对象的方法调用,而不是模拟对象,您可能已经在其上设置了操作/期望。如何创建仅将特定方法委托给真实对象的部分模拟,并将所有其他方法调用委托给模拟对象?
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Invoke;
class MockFoo : public Foo {
public:
MockFoo() {
// By default, all calls are delegated to the real object.
ON_CALL(*this, DoThis())
.WillByDefault(Invoke(&real_, &Foo::DoThis));
ON_CALL(*this, DoThat(_))
.WillByDefault(Invoke(&real_, &Foo::DoThat));
...
}
MOCK_METHOD0(DoThis, ...);
MOCK_METHOD1(DoThat, ...);
...
private:
Foo real_;
};
...
MockFoo mock;
EXPECT_CALL(mock, DoThis())
.Times(3);
EXPECT_CALL(mock, DoThat("Hi"))
.Times(AtLeast(1));
... use mock in test ...
Run Code Online (Sandbox Code Playgroud)
模拟应该简单地扩展真实对象,而不是创建真实对象的实例作为成员变量,然后默认情况下将所有调用委托给父对象。您现在可以像往常一样设置模拟;设置 newON_CALL将覆盖对父级的默认调用。我们让多态为我们完成工作——所有调用,甚至来自父(真实)对象的调用,都会调用模拟对象,然后将ON_CALL语句设置为调用父对象或模拟行为。我们已经成功地将真实对象行为与模拟行为混合在一起。这与将调用委托给父类完全相同。
class Foo {
public:
virtual ~Foo();
virtual void Pure(int n) = 0;
virtual int Concrete(const char* str) { ... }
};
class MockFoo : public Foo {
public:
// Mocking a pure method.
MOCK_METHOD1(Pure, void(int n));
// Mocking a concrete method. Foo::Concrete() is shadowed.
MOCK_METHOD1(Concrete, int(const char* str));
// Use this to call Concrete() defined in Foo.
int FooConcrete(const char* str) { return Foo::Concrete(str); }
};
using ::testing::Invoke;
// Create mock instance foo.
...
// Delegate to parent.
ON_CALL(foo, Concrete(_))
.WillByDefault(Invoke(&foo, &MockFoo::FooConcrete));
Run Code Online (Sandbox Code Playgroud)
这种技术的唯一缺点是它需要大量样板代码并且对代码更改很敏感。我扩展了 googlemock 来简化这个过程;代码可在此处获得。它将生成默认情况下为所有方法调用父(真实)对象的部分模拟,并生成将参数传递给父构造函数的匹配构造函数。
| 归档时间: |
|
| 查看次数: |
5427 次 |
| 最近记录: |