Как установить ожидание для издевательского метода, который вызывается внутри другого издевательского метода C

#c #googlemock

Вопрос:

Я новичок в Google testing framework и искал решение этого вопроса на SO, но не смог найти никаких решений в отношении C . В любом случае, вот что я пытаюсь сделать. У меня есть государственная машина(служба), которая вызывается внутри клиентского кода.

 //IStateMachine.h  class IStateMachine  {  public:  bool Run(const std::stringamp; action) = 0;   bool IsTxnValid(const std::stringamp; action)= 0;  }    //StateMachine.h  class StateMachine : public IStateMachine  {  bool Run(const std::stringamp; action) override;  bool IsTxnValid(const std::stringamp; action) override;    }    //StateMachine.cpp  bool StateMachine::IsTxnValid(const std::stringamp; action)  {  //Checks whether the given action is valid for the given state.  }    bool StateMachine::Run(const std::stringamp; action)  {  if(IsTxnValid(action)) // #E   {  //Do processing  return true;  }  return false;  }   //Client.h contains a class Client which has function called RunService.  Client  {    public:  void RunService();  std::unique_ptrlt;IStateMachinegt; service_; // Initialised to a non null value in either ctr or   // factory.  }    //Client.cpp  bool Client::RunService(std::stringamp;action)  {  if(!service_-gt;Run(action)) //Run in turn calls IsTxnValid().  {  return false;  }  return true;  }  

Сейчас я пишу тестовый пример для проверки функционирования RunService . Я ожидаю, что если Client::IsTxnValid(param) возвращает false, то так и должно RunService быть .

Я успешно настроил рецепт тестирования и смог запустить основные тесты. Вот соответствующий тест, который я написал. При запуске этого теста я получаю ошибку, которая IsTransitionValid никогда не вызывается.

 TEST_F(ClientTest, RunService) {   EXPECT_CALL(*p_service, Run("some_action")); // #A  // EXPECT_CALL(*p_service, Run(testing::_)).WillOnce(::testing::Return(true)); //#B  EXPECT_CALL(*p_service,IsTransitionValid(testing::_)).WillOnce(::testing::Return(false)); //#C : This never gets called.   EXPECT_EQ(false, x_client-gt;RunService());  }  

Как мне правильно позвонить IsTransitionValid ?

Комментарии:

1. Не забудьте добавить виртуальный dtor в IStateMachine

Ответ №1:

Вам не нужно устанавливать это ожидание. Я бы пошел еще дальше: вы даже не должны зависеть от реализации Run in IStateMachine : вас должно волновать только то, какие входные данные он предоставляет (параметры, проверенные с помощью сопоставителей) и какие выходные данные он может возвращать (так что в основном только контракт между этими двумя классами), и в этом вся прелесть!

Это деталь реализации StateMachine класса (реальная реализация), что делается при Run вызове. Единственное, что вам нужно проверить в своем тесте, — это действовать в соответствии с результатом Run . Использование правила тройного А (упорядочить, действовать, утверждать): вы упорядочиваете условия тестового случая (используя EXPECT_CALL s), затем действуете (вызываете RunService ), а затем утверждаете (проверяете результат RunService ).

Технические детали: Когда вы создаете макет, унаследовав от class Foo :

 class Foo { public:  virtual ~Foo() = default;  virtual void bar() = 0; }  

Путем определения:

 class FooMock : public Foo {  MOCK_METHOD0( bar, void()); }  

gmock добавит bar (метод для переопределения) и gmock_bar (внутренние сведения о gmock) методы в FooMock класс. bar в данном случае имеет пустую реализацию. FooImpl и FooMock разделяют интерфейс, но имеют разные реализации — следовательно, в нем не выполняется вызов IsTxnValid Run : макет класса просто не знает (и не заботится) о том, как Run он реализован StateMachine . Помните: в своем тестовом наборе вы взаимодействуете с StateMachineMock ним, и вас интересует только взаимодействие с его общедоступным интерфейсом, контракт между этими двумя классами и то, как они взаимодействуют друг с другом.

Тем не менее, вам, конечно, нужно протестировать StateMachine класс. Это может зависеть от еще одного интерфейса в его реализациях: он будет протестирован с другим набором насмешек. Но Client не должен знать об этом.