Ожидайте, что некоторый метод был вызван на фиктивном объекте.Это нарушает инкапсуляцию? - PullRequest
0 голосов
/ 02 апреля 2019

Рассмотрим следующий код:

class SomeInterface
{
public:
    virtual void foo() = 0;
    virtual ~SomeInterface() {}
};

class RealImplementation : public SomeInterface
{
public:
    void foo() { /* do complete stuff */}
};

class MockImplementation : public SomeInterface
{
public:
    void foo() { /* do simple stuff */ }
};

Чтобы быть более конкретным, есть пример:

class IInjector
{
public:
    virtual bool injectDLL() const = 0;
    virtual ~IInjector() {}
};

class RealInjector : public IInjector
{
public:
    bool injectDLL() const
    {
        int pid = GetHookedProcessId();
        char name = readDllNameFromSomewhere();
        if (loadDllInSomeProcess(pid, name))
            return true;
        else
            return false;
    }
};

class Hook
{
public:
    bool hookProcess(const IInjector& injector)
    {
        return injector.injectDLL();
    }
};

Тогда в тестовом коде это обычный случай, чтобы сделать что-то вроде этого:

class MockInjector : public IInjector {
public:
    MOCK_METHOD0(injectDLL, bool());
};

TEST(HookTest, CanHookSomething) {
    MockInjector injector;                          
    EXPECT_CALL(injector, injectDLL()).Times(1);

    Hook hook;
    EXPECT_TRUE(hook.hookProcess(injector));
}

Для проверки того, что был вызван метод injectDLL, мы должны знать, что hookProcess вызвал injectDLL.Но это детали реализации метода hookProcess.Итак, в нашем тесте мы раскрываем некоторые детали реализации.Но это очень распространенный случай.Итак, можно ли открыть некоторые детали реализации при использовании mocks?

Ответы [ 2 ]

1 голос
/ 14 апреля 2019

Юнит-тестирование обычно применяется как метод тестирования белого ящика - вы знаете тестируемый код. В противном случае вы также не сможете делать заявления о покрытии кода, достигнутого вашими тестами. И код модульного теста считается принадлежащим к коду, помещенному под контроль версий вместе с кодом и т. Д. Таким образом, для вашего модульного теста вы не «раскрываете» детали реализации - они все равно не скрыты.

Однако, безусловно, с помощью имитации ваши тесты становятся все более зависимыми от деталей реализации, что означает, что они с большей вероятностью сломаются или нуждаются в обслуживании. Но это просто компромисс, который вам, возможно, придется принять в этом случае.

0 голосов
/ 29 апреля 2019

Если спецификация функции Hook::injectProcess должна использовать предоставленный пользователем экземпляр IInjector для внедрения DLL, любая реализация injectProcess, которая не вызывает метод injectDLL для этого предоставленного пользователем экземпляра, несомненно сломана. Таким образом, в приведенном вами примере, похоже, нет никакого нарушения инкапсуляции.

Пример, который вы демонстрируете, является хорошим примером внедрения зависимостей, идеально подходящего для тестирования с такими фреймворками, как Google Test. Он позволяет смоделировать некоторые конкретные операции, которые формализованы в открытых интерфейсах, путем вызова открытых функций с помощью создаваемых пользователем фиктивных объектов.

Однако в общем случае подобный код может нарушить инкапсуляцию. Считайте, что тестируемая функция не является методом hookProcess, чье четко определенное задание заключается в внедрении DLL, так что вы точно знаете, что DLL должна быть внедрена. Возможно, вы захотите протестировать функцию, которая должна получать некоторые данные, и в настоящее время для этого нужно внедрить некоторые библиотеки DLL в некоторые процессы, но могут быть другие способы получения этой информации, которые не включают в себя внедрение DLL или внедрение различных библиотек DLL в разные процессы. , В этом случае проверка, для каких библиотек DLL внедряется, когда действительно нарушает инкапсуляцию, предоставляемую спецификацией «просто получить информацию в любом случае». Этот случай обсуждается ответом Дирка Херрманна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...