Избегайте в тестах слишком большого количества макетов со статической переменной в исходном коде

#c #googletest #googlemock

Вопрос:

Я пытаюсь выполнить несколько тестов за один раз (используя GoogleTest) в исходном коде, который я написал, содержащем static const переменную, инициализированную через сеть (которая «издевается», чтобы имитировать реальное поведение).

Пример static const std::string myStr{getNameFromNetwork()};

Дело в том, что в первом тесте макет включен getNameFromNetwork() нормально, но со второго по последний тест макет слишком велик, потому что переменная статична И уже инициализирована.

Есть ли у вас какие-либо предложения по решению этой проблемы ?

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

1. Можете ли вы привести минимальный, самодостаточный пример, который воспроизведет проблему?

2. @TimRandall В этом случае код на самом деле не нужен, это скорее вопрос дизайна

Ответ №1:

Короче говоря: избавьтесь от ВСЕХ ваших глобальных данных, поскольку, как вы выяснили, глобальные данные затрудняют тестирование. Решение, которое вы ищете, называется внедрением зависимостей. Резюме : Поместите все ваши предыдущие данные в объект со стандартизированным интерфейсом и вставьте их в код, которому нужны данные. И считывайте свои данные через этот интерфейс.

Пример :

 #include <iostream>
#include <string>

// remove ALL you globals
// static const std::string myStr{ getNameFromNetwork() }; <== remove ALL globals

// define an interface (abstract baseclass) with getters to your data
struct global_data_itf
{
    virtual const std::stringamp; get_name_from_network() const = 0;
    virtual ~global_data_itf() = defau<

protected:
    global_data_itf() = defau<
};

//-----------------------------------------------------------------------------
// provide an implementation with all your previous global settings

struct global_data :
    global_data_itf
{
    const std::stringamp; get_name_from_network() const override
    {
        return myStr;
    }

    std::string myStr{ "network_name" };
};

//-----------------------------------------------------------------------------

class your_class
{
public:

    your_class(const global_data_itfamp; data) :
        m_data{ data }
    {
    }

    void connect()
    {
        // instead of using static data use data from injected interface
        std::cout << m_data.get_name_from_network() << std::endl;
    }

private:
    const global_data_itfamp; m_data;
};

//-----------------------------------------------------------------------------
// test with default values

void test_case_1()
{
    global_data data;
    your_class object(data);

    object.connect();
}

//-----------------------------------------------------------------------------
// if you need to test with different configs/global data
// just instantiate a mock in you rest case

struct global_data_mock :
    global_data_itf
{
    const std::stringamp; get_name_from_network() const override
    {
        return myStr;
    }

    std::string myStr{ "some other network name" };
};

void test_case_2()
{
    global_data_mock data;
    your_class object(data);
    object.connect();
}

//-----------------------------------------------------------------------------

int main()
{
    test_case_1();
    test_case_2();
    return 0;
}