Я придумал одно решение, это не самое хорошее, но приемлемое ИМО.
Код:
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
, для каждого вызова метода foo
с аргументом 0
.
В этом действии мы вызываем лямбду, которая использует макрос GTest ADD_FAILURE()
для генерациинефатальный сбой - эквивалент EXPECT_*
макросов.Вместо этого вы можете использовать FAIL()
для фатального сбоя, как в макросах ASSERT_*
.
Мы используем макрос 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
и лямбд.