У меня есть следующая настройка:
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 — это виртуальная функция, она должна вернуть пустой вектор данных как результат смоделированного. Почему этого не происходит?
В конце концов, тест завершается сбоем, потому что у бэкенда нет инициализации его членов.
пожалуйста, покажите минимальный воспроизводимый пример, но это не похоже на то, что Process
использует ваш фиктивный объект?
Иван, отредактировал мой вопрос, добавив больше деталей. Сбой теста внутри GetData из-за того, что серверные части не инициализированы.
Алан, Process инициализирует DataFetcher внутри себя. И да, он не использует мой фиктивный объект. Это должно... Верно?
Вам нужно заменить DataFetcher data_fetcher(backends);
на MockDataFetcher data_fetcher(backends);
. Код, реализованный в настоящее время, жестко закодирован DataFetcher
, но для того, чтобы его можно было тестировать, его нужно не жестко закодировать, а вместо этого передать.
Class
не является ключевым словом C++, похоже, вы даже не используете C++.
Из вашего заявления:
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 не может быть ссылкой, поскольку объект, на который она ссылается, буквально не имеет срока жизни. Любая попытка использовать «данные» приведет к неопределенному поведению.
использование константной ссылки на временное не обязательно является ошибкой (хотя, вероятно, это не предполагаемое поведение здесь)
Это неверно из-за применимого здесь продления срока службы.
Функция вообще не использует объект mock
:
void Process(const Backends& backends) {
DataFetcher data_fetcher(backends);
...
const auto& data = data_fetcher.GetData(q);
...
}
Независимо от того, создаете ли вы MockDataFetcher
функцию Process
create local DataFetcher
и используете ее, а не mock
, которую вы создали в тестовом примере, вам нужно как-то предоставить ее функции Process
.
Можете ли вы объяснить, какое значение
GetData
вернулось?