У меня есть класс, который принимает логическое значение в качестве ссылочного параметра и возвращает целое число:
class Foo
{
public:
Bar my_bar;
virtual int myMethod(bool &my_boolean) = 0;
}
/*...*/
int Foo::myMethod(bool &my_boolean){
if (my_bar == NULL){
my_boolean = false;
return -1;
}
else{
my_boolean = true;
return 0;
}
}
И я создал макет для этого класса:
class MockFoo : public Foo
{
MOCK_METHOD1(myMethod,int(bool &my_boolean));
}
У меня проблемы с тем, как установить ожидания для такого рода функции, потому что мне нужно установить возвращаемое значение а также параметр ссылки на конкретные значения для правильного создания моих модульных тестов. Как я могу справиться с такого рода функциями с помощью gmock? Я попытался следовать тому, что, по моему мнению, было решением в документации:
using ::testing::SetArgPointee;
class MockMutator : public Mutator {
public:
MOCK_METHOD2(Mutate, void(bool mutate, int* value));
...
};
...
MockMutator mutator;
EXPECT_CALL(mutator, Mutate(true, _))
.WillOnce(SetArgPointee<1>(5));
Но либо я не понял пример, либо он не подходит для этого случая. Кто-нибудь имел дело с такой ситуацией раньше?
Заранее спасибо.
Ваш вопрос трудно получить! Образцы из Google издевается над «кулинарной книгой» так же хорошо.
Вы хотите повторно использовать реализацию для Foo::myMethod()
с вашим фиктивным классом, или вы просто хотите имитировать побочные эффекты (возвращаемое значение и изменяемые параметрами ref) для конкретных ситуаций вызова?
Поддельный класс обычно предназначен для замены / симуляции вашего Foo
класс, чтобы не наследовать это напрямую или это поведение. Не знаю, будет ли работать способ определения поведения по умолчанию для чистого метода, но сомневаюсь в этом. Вы можете просто опустить = 0
затем.
Лучшим подходом было бы выделить реальное объявление интерфейса, например:
struct IFoo
{
virtual int myMethod(bool &my_boolean) = 0;
virtual ~IFoo() {}
};
class Foo : public IFoo
{
// ...
};
class MockFoo : public IFoo
{
MOCK_METHOD1(myMethod,int(bool &my_boolean));
};
Если у вас есть последний случай, вы должны отделаться testing::Return(value)
а также testing::SetArgReferee<N>(value)
(обнаружил, что в очень полезном Шпаргалка).
Ваш ожидающий вызов должен выглядеть так:
MockFoo foo;
// Expect call to myMethod() return -1 and set the by ref argument to true
EXPECT_CALL(foo, myMethod(_))
.WillOnce(DoAll(SetArgReferee<0>(true),Return(-1)));
// Expect call to myMethod() return 0 and set the by ref argument to false
EXPECT_CALL(foo, myMethod(_))
.WillOnce(DoAll(SetArgReferee<0>(false),Return(0)));
Если вы действительно хотите использовать свою оригинальную логику классов для myMethod()
посмотри на «Делегирование звонков родительскому классу», соответственно «Делегирование вызовов реальному объекту»
Других решений пока нет …