QSignalSpy vs Mocks: Сравнение подходов к тестированию сигналов в Qt

Автор: | 20 июня, 2025

Сравнение подходов

ХарактеристикаQSignalSpyМоки (например, Google Mock)
ЦельОтслеживание вызова сигналовПроверка вызова методов, поведения объектов
Сфера примененияQt-ориентированные проекты (QObject)Общий C++ (без привязки к Qt)
Проверка сигналовДа (встроено)Нет напрямую, но можно проверить вызов слотов
Тип контроляПассивное наблюдение за сигналомАктивная проверка вызова метода, через ожидания
Работает с сигналами/слотамиДа (QObject::connect)Только методы, нет сигналов (без обёртки)
Асинхронная поддержкаДа (spy.wait(timeout))Требует внешней синхронизации
Проверка аргументовДа (spy.at(i).at(j)) через QVariantДа (точное сравнение типов и значений аргументов)
Интеграция с QtПолная (QtTest, QObject)Ограниченная (обычно сторонние библиотеки)
Инструмент MockingНе поддерживаетПоддерживает (EXPECT_CALL, ON_CALL, т.д.)
ПотокиТолько в основном потокеМожно использовать и в других потоках
Лёгкость использованияОчень прост в QtТребует подготовки мок-классов

Пример: QSignalSpy

class Worker : public QObject {
    Q_OBJECT
signals:
    void done(int result);
};

void testSignalWithSpy() {
    Worker w;
    QSignalSpy spy(&w, SIGNAL(done(int)));

    emit w.done(123);

    QCOMPARE(spy.count(), 1);
    QList<QVariant> args = spy.takeFirst();
    QCOMPARE(args.at(0).toInt(), 123);
}

Пример: Мок через Google Mock

class Receiver {
public:
    virtual void onDone(int result) = 0;
    virtual ~Receiver() = default;
};

class MockReceiver : public Receiver {
public:
    MOCK_METHOD(void, onDone, (int), (override));
};

void testWithMock() {
    MockReceiver mock;
    EXPECT_CALL(mock, onDone(123)).Times(1);

    Worker w;
    QObject::connect(&w, &Worker::done, [&mock](int r) {
        mock.onDone(r);
    });

    emit w.done(123);
}

Что выбрать?

СценарийИспользовать
Проверить факт вызова сигналаQSignalSpy
Проверить аргументы сигналаQSignalSpy
Проверить поведение сложного компонента, реагирующего на сигналMock
Нужно протестировать последовательность вызовов, состоянияMock
Вы не используете QtMock
Вы используете Qt GUI/slotsQSignalSpy

Итого

QSignalSpyМоки (Google Mock и др.)
✅ Легко применим в Qt✅ Гибкие ожидания, поведение
✅ Не требует дополнительных классов⛔ Требует интерфейсов, описания классов
⛔ Работает только с сигналами✅ Можно подменить любую часть системы
✅ Хорошо работает с асинхронным кодом⛔ Требуется внешняя синхронизация

Комбинированный подход

Ты можешь использовать оба подхода:

  • QSignalSpy — чтобы проверить, что сигнал был отправлен.
  • Моки — чтобы проверить, что получатель отреагировал должным образом.