Подтвердить что ты не робот

Google макет метода ByRef

У меня есть класс, который принимает логическое значение в качестве ссылочного параметра и возвращает целое число:

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));

Но либо я не понял этот пример, либо он не применим для этого случая. Кто-нибудь имел дело с такой ситуацией раньше?

Спасибо заранее.

4b9b3361

Ответ 1

Ваш вопрос трудно получить! Образцы из Google издевается над "кулинарной книгой" так же хорошо.

Вы хотите повторно использовать реализацию для Foo::myMethod() с вашим 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(), посмотрите "Делегирование вызовов родительскому классу", соответственно. "Делегирование вызовов реальному объекту"