Виртуальный метод в С++ не высмеивается. Что мне здесь не хватает?

У меня есть следующая настройка:

Class DataFetcher {
  public:
    virtual ~DataFetcher() = default;
    explicit DataFetcher(const Backends& backends);

    virtual vector<Data> GetData(const vector<string>& q) const;

  private:
    Backends backends_;
};

Выполнение:

vector<Data> DataFetcher::GetData(const vector<string>& q) {
  cout << "Yikes! This was called";
  ...
}

Затем часть функции в другом месте, которая использует ее как:

void Process(const Backends& backends) {
  DataFetcher data_fetcher(backends);
  ...
  const auto& data = data_fetcher.GetData(q);
  ...
}

Теперь я пытаюсь протестировать Process с любым вызовом GetData, над которым издеваются, следующим образом:

class MockDataFetcher : public DataFetcher {
  public:
    using DataFetcher::DataFetcher;
    MOCK_METHOD(vector<Data>, GetData, (const vector<string>& q), (const, override));
}

class ActualLogicTest : public ... {
  protected:
    Backends backends_;
}

TEST_F(ActualLogicTest, BasicOne) {
  MockDataFetcher mock_data_fetcher(backends_);
  vector<Data> data;
  ON_CALL(mock_data_fetcher, GetData).WillByDefault(Return(data));
  ...
  Process(backends_);
}

Что в этом не так? Я вижу, что фактическая реализация GetData вызывается, и я также вижу это сообщение Yikes! This was called. Поскольку GetData — это виртуальная функция, она должна вернуть пустой вектор данных как результат смоделированного. Почему этого не происходит?

В конце концов, тест завершается сбоем, потому что у бэкенда нет инициализации его членов.

Можете ли вы объяснить, какое значение GetData вернулось?

Ivan Venkov 03.02.2023 11:10

пожалуйста, покажите минимальный воспроизводимый пример, но это не похоже на то, что Process использует ваш фиктивный объект?

Alan Birtles 03.02.2023 11:13

Иван, отредактировал мой вопрос, добавив больше деталей. Сбой теста внутри GetData из-за того, что серверные части не инициализированы.

Bit Manipulator 03.02.2023 11:18

Алан, Process инициализирует DataFetcher внутри себя. И да, он не использует мой фиктивный объект. Это должно... Верно?

Bit Manipulator 03.02.2023 11:20

Вам нужно заменить DataFetcher data_fetcher(backends); на MockDataFetcher data_fetcher(backends);. Код, реализованный в настоящее время, жестко закодирован DataFetcher, но для того, чтобы его можно было тестировать, его нужно не жестко закодировать, а вместо этого передать.

Eljay 03.02.2023 13:28
gmock для языка Groovy, ваш код C++. Вам нужен ответ Groovy? Class не является ключевым словом C++, похоже, вы даже не используете C++.
273K 03.02.2023 15:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Из вашего заявления:

virtual vector<Data> GetData(const vector<string>& q) const;

GetData() возвращает объект.

Тем не менее, в Process()

void Process(const Backends& backends) {
  DataFetcher data_fetcher(backends);
  ...
  const auto& data = data_fetcher.GetData(q);  // BUG!! Why is data a reference?

}

Переменная data не может быть ссылкой, поскольку объект, на который она ссылается, буквально не имеет срока жизни. Любая попытка использовать «данные» приведет к неопределенному поведению.

использование константной ссылки на временное не обязательно является ошибкой (хотя, вероятно, это не предполагаемое поведение здесь)

Alan Birtles 03.02.2023 11:14

Это неверно из-за применимого здесь продления срока службы.

Fureeish 03.02.2023 11:21
Ответ принят как подходящий

Функция вообще не использует объект mock:

void Process(const Backends& backends) {
  DataFetcher data_fetcher(backends);
  ...
  const auto& data = data_fetcher.GetData(q);
  ...
}

Независимо от того, создаете ли вы MockDataFetcher функцию Process create local DataFetcher и используете ее, а не mock, которую вы создали в тестовом примере, вам нужно как-то предоставить ее функции Process.

Другие вопросы по теме