全局检查模拟中的值
Globally check value in mock
我有一个模拟 API 包装器。
class MockApiWrapper : public ApiWrapper {
public:
MockNrfWrapper();
virtual ~MockNrfWrapper();
MOCK_METHOD1(api_do, void(int param));
};
让我们假设 api_do
不应该用 param = 0
调用。因为我使用这个模拟 "everywhere",所以我想在对 api_do
的每个调用中附加一个 assertion/expect。示例:
void MyClass::InvalidCallsToApi(void) {
// api->api_do(0); // Fails "global assert"
// api->api_do(1); // Fails by specific test
api->api_do(2); // Valid call
}
TEST(MyTestCase, FirstTest) {
// Mock always checks that api_do is not called
// with argument of 0
EXPECT_CALL(api, api_do(Ne(1));
uut->InvalidCallsToApi();
}
我尝试在构造函数中使用 ON_CALL
和 Invoke
来执行此操作,但它要么被测试中添加的 EXPECT 覆盖,要么出现编译错误(无法执行 ASSERT或调用调用中的 EXPECT)。
我希望我的问题陈述清楚。在此先感谢您的任何意见!
我想出了一个解决方案,它不是最好的,但可以接受 IMO。
代码:
struct BInterface {
virtual void foo(int) = 0;
};
struct BMock : public BInterface {
MOCK_METHOD1(foo, void(int));
BMock() {
ON_CALL(*this, foo(0))
.WillByDefault(::testing::InvokeWithoutArgs([](){ADD_FAILURE() << "This function can't be called with argument 0";}));
}
};
void testedMethod(int a) {
BInterface* myB = new BMock;
myB->foo(a);
delete myB;
}
TEST(myTest, okCase) {
testedMethod(1);
}
TEST(myTest, notOkCase) {
testedMethod(0);
}
解释:
我们为 BMock
添加一个默认操作,用于每次调用带有参数 0
的 foo
方法。
在此操作中,我们调用 lambda,它使用 GTest 宏 ADD_FAILURE()
生成非致命失败 - 相当于 EXPECT_*
宏。您可以使用 FAIL()
代替 ASSERT_*
宏中的致命故障。
我们在 mock 的构造函数中使用了 ON_CALL
宏,这样可以避免使用其他所有 mock 对象调用它。
限制:
例如,同样的技巧不适用于 EXPECT_CALL
- 我不知道 GMock 实现,但我假设 EXPECT_CALL
需要一个完全初始化的对象。
使用匹配器接受 0
的调用仍然会通过(即 EXPECT_CALL(myB, foo(::testing::_));
,但在所有其他 GMock 期望中都是这种情况。当遇到新的期望时,GMock 总是会掩盖旧的期望。你必须以这样一种方式来创建您的期望,即它们不会覆盖以前的期望。
将 .RetiresOnSaturation()
添加到您的所有 EXPECT_CALL
将确保在他们不感兴趣时将呼叫转发到默认操作(由 ON_CALL
设置)。
当有多个不允许的值时,自定义匹配器会很有帮助。
MATCHER(IsValidApiArg, ""){return arg == 0 || arg == 1;}
ON_CALL(*this, api_foo(!IsValidApiArg)
.WillByDefault(::testing::InvokeWithoutArgs([](){ADD_FAILURE();}));
EXPECT_CALL(myMock, api_foo(IsValidApiArg));
注意:我仍然无法相信 GMock 不提供简单地生成故障的默认操作。也许你可以在文档的深处找到更合适的东西。
您还可以为此创建一个自定义操作,以避免所有 Invoke
和 lambdas.
我有一个模拟 API 包装器。
class MockApiWrapper : public ApiWrapper {
public:
MockNrfWrapper();
virtual ~MockNrfWrapper();
MOCK_METHOD1(api_do, void(int param));
};
让我们假设 api_do
不应该用 param = 0
调用。因为我使用这个模拟 "everywhere",所以我想在对 api_do
的每个调用中附加一个 assertion/expect。示例:
void MyClass::InvalidCallsToApi(void) {
// api->api_do(0); // Fails "global assert"
// api->api_do(1); // Fails by specific test
api->api_do(2); // Valid call
}
TEST(MyTestCase, FirstTest) {
// Mock always checks that api_do is not called
// with argument of 0
EXPECT_CALL(api, api_do(Ne(1));
uut->InvalidCallsToApi();
}
我尝试在构造函数中使用 ON_CALL
和 Invoke
来执行此操作,但它要么被测试中添加的 EXPECT 覆盖,要么出现编译错误(无法执行 ASSERT或调用调用中的 EXPECT)。
我希望我的问题陈述清楚。在此先感谢您的任何意见!
我想出了一个解决方案,它不是最好的,但可以接受 IMO。
代码:
struct BInterface {
virtual void foo(int) = 0;
};
struct BMock : public BInterface {
MOCK_METHOD1(foo, void(int));
BMock() {
ON_CALL(*this, foo(0))
.WillByDefault(::testing::InvokeWithoutArgs([](){ADD_FAILURE() << "This function can't be called with argument 0";}));
}
};
void testedMethod(int a) {
BInterface* myB = new BMock;
myB->foo(a);
delete myB;
}
TEST(myTest, okCase) {
testedMethod(1);
}
TEST(myTest, notOkCase) {
testedMethod(0);
}
解释:
我们为 BMock
添加一个默认操作,用于每次调用带有参数 0
的 foo
方法。
在此操作中,我们调用 lambda,它使用 GTest 宏 ADD_FAILURE()
生成非致命失败 - 相当于 EXPECT_*
宏。您可以使用 FAIL()
代替 ASSERT_*
宏中的致命故障。
我们在 mock 的构造函数中使用了 ON_CALL
宏,这样可以避免使用其他所有 mock 对象调用它。
限制:
例如,同样的技巧不适用于 EXPECT_CALL
- 我不知道 GMock 实现,但我假设 EXPECT_CALL
需要一个完全初始化的对象。
使用匹配器接受 0
的调用仍然会通过(即 EXPECT_CALL(myB, foo(::testing::_));
,但在所有其他 GMock 期望中都是这种情况。当遇到新的期望时,GMock 总是会掩盖旧的期望。你必须以这样一种方式来创建您的期望,即它们不会覆盖以前的期望。
将 .RetiresOnSaturation()
添加到您的所有 EXPECT_CALL
将确保在他们不感兴趣时将呼叫转发到默认操作(由 ON_CALL
设置)。
当有多个不允许的值时,自定义匹配器会很有帮助。
MATCHER(IsValidApiArg, ""){return arg == 0 || arg == 1;}
ON_CALL(*this, api_foo(!IsValidApiArg)
.WillByDefault(::testing::InvokeWithoutArgs([](){ADD_FAILURE();}));
EXPECT_CALL(myMock, api_foo(IsValidApiArg));
注意:我仍然无法相信 GMock 不提供简单地生成故障的默认操作。也许你可以在文档的深处找到更合适的东西。
您还可以为此创建一个自定义操作,以避免所有 Invoke
和 lambdas.