如何为输入参数匹配联合中元素的值,例如 - 如果我模拟具有以下签名的方法 -
struct SomeStruct
{
int data1;
int data2;
};
void SomeMethod(SomeStruct data);
如何匹配该方法的模拟在参数中使用正确的值调用?
After reading through the Google mock documentation in detail, I solved my problem as documented in Defining Matchers section. (An example would have been great!)
So the solution is to use the MATCHER_P
macros to define a custom matcher. So for the matching SomeStruct.data1
I defined a matcher:
MATCHER_P(data1AreEqual, ,"") { return (arg.data1 == SomeStructToCompare.data1); }
to match it in an expectation I used this custom macro like this:
EXPECT_CALL(someMock, SomeMethod(data1AreEqual(expectedSomeStruct)));
Here, expectedSomeStruct
is the value of the structure.data1
we are expecting.
Note that, as suggested in other answers (in this post and others), it requires the unit under test to change to make it testable. That should not be necessary! E.g. overloading.
如果需要显式测试结构的一个字段(或类的一个“属性”)的特定值,gmock 有一种简单的方法可以使用“字段”和“属性”定义进行测试。使用结构:
EXPECT_CALL( someMock, SomeMethod( Field( &SomeStruct::data1, expectedValue )));
或者,或者,如果我们有 SomeClass(而不是 SomeStruct),它具有私有成员变量和公共 getter 函数:
EXPECT_CALL( someMock, SomeMethod( Property( &SomeClass::getData1, expectedValue )));
谷歌提供了一些关于使用 gmock 的很好的文档,其中充满了示例代码。我强烈建议检查一下:
https://github.com/google/googletest/blob/master/googlemock/docs/cook_book.md#using-matchers
正如您所指出的,==
不会为类类型(包括 POD)自动创建默认相等运算符 ( )。由于 gmock 在匹配参数时使用此运算符,因此您需要显式定义它才能像使用任何其他类型一样使用该类型(如下所示):
// Assumes `SomeMethod` is mocked in `MockedObject`
MockedObject foo;
SomeStruct expectedValue { 1, 2 };
EXPECT_CALL(foo, SomeMethod(expectedValue));
因此,最直接的处理方法是为结构定义一个相等运算符:
struct SomeStruct
{
int data1;
int data2;
bool operator==(const SomeStruct& rhs) const
{
return data1 == rhs.data1
&& data2 == rhs.data2;
}
};
如果您不想走那条路,可以考虑使用字段匹配器根据其成员变量的值来匹配参数。(但是,如果测试对比较结构实例之间的相等性感兴趣,那么这很好地表明其他代码也会感兴趣。因此,只定义一个operator==
并完成它可能是值得的。)
也许没用,因为很久以前就已经回答了这个问题,但这里有一个适用于任何结构且不使用 MATCHER 或 FIELD 的解决方案。
假设我们正在检查:methodName(const Foo& foo):
using ::testing::_;
struct Foo {
...
...
};
EXPECT_CALL(mockObject, methodName(_))
.WillOnce([&expectedFoo](const Foo& foo) {
// Here, gtest macros can be used to test struct Foo's members
// one by one for example (ASSERT_TRUE, ASSERT_EQ, ...)
ASSERT_EQ(foo.arg1, expectedFoo.arg1);
});
上面基本上已经回答了,但我想再举一个很好的例子:
// some test type
struct Foo {
bool b;
int i;
};
// define a matcher if ==operator is not needed in production
MATCHER_P(EqFoo, other, "Equality matcher for type Foo") {
return std::tie(arg.b, arg.i) == std::tie(other.b, other.i);
}
// example usage in your test
const Foo test_value {true, 42};
EXPECT_CALL(your_mock, YourMethod(EqFoo(test_value)));