Google Test и Google Mock не работают с внешними глобальными переменными

#c #unit-testing #googletest #googlemock

#c #модульное тестирование #googletest #googlemock

Вопрос:

Я пытаюсь использовать google test и google mock протестировать свой простой класс C . Мой макет класса выглядит так:

 #pragma once

#include "base_classes/_HardwareSerial.h"
#include "gmock/gmock.h"

class HardwareSerial : public _HardwareSerial
{
public:
    HardwareSerial() = default;
    MOCK_METHOD(void, begin, (unsigned long baud_rate), (override));
    MOCK_METHOD(void, end, (), (override));
    MOCK_METHOD(void, print, (const __FlashStringHelper *in_flash_str), (override));
    MOCK_METHOD(void, print, (const char *str), (override));
};

extern HardwareSerial Serial;
 

Теперь я использую этот макет класса в своем тестовом файле cpp:

 #include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "HardwareSerial.h"

using ::testing::_;

HardwareSerial Serial; // <<< Putting this here does NOT work. The test passes whatever if the function has never been called called 10000 times. The test just passes.. This is the problem I have.

HardwareSerial AnotherNewSerial; // <<< Does NOT work.

class Test_Class: public ::testing::Test
{
protected:
    HardwareSerial Serial; // <<< Putting this here makes the test working, but of course if anything relies on the global extern variable will cause compilation error.
    HardwareSerial AnotherNewSerial; // <<< Works.

    void SetUp() override
    {
    }

    void TearDown() override
    {
    }
};

TEST_F(Test_Class, MYTEST)
{
    EXPECT_CALL(Serial, begin(_))
        .Times(10);
}
 

Определение внешней HardwareSerial Serial переменной в глобальной области в моем тесте приводит к тому, что тест проходит все, что я делаю с этой переменной. Так что мой EXPECT_CALL just не приводит к сбою теста, не заботясь о том, был ли begin вызван метод или нет. Это просто всегда проходит!

Однако перемещение объявления в класс заставляет тест работать так, как ожидалось. Однако я не могу полагаться на это, потому что у меня есть другие компоненты, которые полагаются на эту глобальную внешнюю переменную. И очень интересно узнать, что здесь происходит и как я могу это исправить?

Обновить:

Кажется, это не имеет ничего общего с extern тем, что объявление новой переменной типа HardwareSerial в глобальной области вызывает точно такую же проблему, а перемещение ее в классы устраняет проблему.

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

1. Я нигде не нашел его официально, но, похоже, создание экземпляра type Google Mocks до инициализации Google test / mock каким-то образом не работает. По-видимому, именно по этой причине у меня возникла проблема, упомянутая выше.

Ответ №1:

TL, DR: как правило, создают фиктивные объекты в качестве членов тестового примера.

Длинное объяснение:

Пожалуйста, ознакомьтесь с вводной частью Google Mock здесь о том, как их использовать, особенно в последнем пункте:

Когда макет уничтожается, gMock автоматически проверяет, были ли удовлетворены все ожидания от него.

(выделено мной жирным шрифтом). Ключевым моментом является то, что EXPECT_CALL s вычисляются по фактическим вызовам, когда макет объекта уничтожается (это обычная вещь в C , зависящая от RAII). Подобный глобальный объект уничтожается при завершении main работы метода программы, поэтому вы не увидите никаких ошибок после завершения тестового примера. Когда макет объекта определен в наборе тестов, он будет создан в начале теста и уничтожен по окончании теста (если быть точным: макет создается в ctor тестового набора и уничтожается при вызове dtor тестового набора. Это делается для каждого тестового примера в данном наборе тестов, если вы используете TEST_F ).