C ++ тестирование приватных методов обратного вызова - PullRequest
1 голос
/ 08 октября 2019

У меня есть класс, который регистрирует свои собственные частные методы вместе с другими классами, которые будут использоваться в качестве обратных вызовов. При этом используется std::bind для создания std::function, указывающего на приватный метод.

Пример: (имена не являются реальными именами классов)

class DataProcessor {
private:
    void callback() {
        // Do something
    };
public:
    DataProcessor(IDataSupplier* supplier) {
        supplier->subscribe(std::bind(&DataProcessor::callback, this));
    };
};

Теперь я хочу убедиться, чтоФункция обратного вызова выполняет правильные действия. Я использую gtest для своих тестов и создаю макет IDataSupplier с gmock, чтобы создать этот объект с.

Я не могу вызвать DataProcessor::callback() напрямую, поскольку он является закрытым при просмотре из теста. Я бы предпочел не менять DataProcessor для моего теста.

Обычно обратный вызов доступен, потому что IDataSupplier имеет доступ к объекту std::function, который упаковывает приватный метод. Поскольку у меня есть поддельная версия IDataSupplier, я не думаю, что смогу перехватить полученный ей обратный вызов (и опять же, неправильно полагаться на это; что если gmock перестанет позволять мнеполучить предоставленный std::function?)

Итак, мои вопросы сводятся к этим двум:

  1. Я делаю плохую вещь (tm), пытаясь протестировать частный метод обратного вызова?
  2. Как мне подойти к тестированию этого обратного вызова, если я вообще должен это делать?

1 Ответ

0 голосов
/ 09 октября 2019

Утром со свежим умом я разобрался с ответом:

С помощью gmock вы можете определить функцию, которая должна вызываться, если вызывается ваша смоделированная функция. Это позволило мне получить обратный вызов, переданный функции подписки, и, таким образом, сохранить обратный вызов для использования в тесте. Следуя приведенному выше примеру:

using ::testing::_;

class UnitTests_DataProcessor : public ::testing::Test {
  std::function<void()> m_dataCallback;
  MockDataSupplier m_dataSupplier;

  std::unique_ptr<DataProcessor> m_dataProcessor;

  void SetUp() override {
    ON_CALL(m_dataSupplier, subscribe(_))
      .WillOnce([this](std::function<void()> callback) { m_dataCallback = callback; });

    m_dataProcessor = std::make_unique<DataProcessor>(m_dataSupplier);
  };
};

TEST_F(UnitTests_DataProcessor, TestCallback) {
  /*
   * Contains the bound callback function of the DataProcessor class, which is still
   * defined private but accessed through the same method as the production code would.
   */
  m_dataCallback();

  // ASSERTIONS
}
...