C++ и Внедрение зависимости в поблочном тестировании

Предположим, что у меня есть класс C++ как так:

class A
{
    public:
        A()
        {

        }

        void SetNewB( const B& _b ) { m_B = _b; }

    private:
        B m_B;
}

Чтобы к модульному тесту что-то вроде этого, я должен был бы повредить зависимость A от B. Так как класс A содержит на фактический объект и не указатель, я должен был бы осуществить рефакторинг этот код для взятия указателя. Кроме того, я должен был бы создать родительский интерфейсный класс для B, таким образом, я могу передать в своей собственной фальшивке B, когда я тестирую SetNewB.

В этом случае не поблочное тестирование с внедрением зависимости далее усложняет существующий код? Если я делаю B указателем, я теперь представляю выделение "кучи", и некоторая часть кода теперь ответственна за чистку его (если я не использую касательно считаемых указателей). Кроме того, если B является довольно тривиальным классом только с несколькими членскими переменными и функциями, почему представляют совершенно новый интерфейс для него вместо того, чтобы просто тестировать с экземпляром B?

Я предполагаю, что Вы могли привести аргумент, что будет легче осуществить рефакторинг при помощи интерфейса. Но есть ли некоторые случаи, где два класса, возможно, должны были бы быть сильно связаны?

5
задан lhumongous 9 April 2010 в 18:04
поделиться

3 ответа

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

9
ответ дан 13 December 2019 в 19:24
поделиться

В зависимости от того, как вы используете B, вы можете использовать std::auto_ptr вместо указателя с подсчетом ссылок. До тех пор, пока вам не нужно передавать ссылку на B чему-то другому, что будет работать и потребует минимальных изменений кода.

0
ответ дан 13 December 2019 в 19:24
поделиться

Если B действительно является зависимостью, инжектированной в A, то вам следует рассмотреть несколько других вариантов. Первый - инжектирование B во время конструирования:

class A
{
    public:
        A( const B& _b ) : m_B(_b) {}

    private:
        const B& m_B;
};

Если вы действительно хотите изменить B во время жизненного цикла вашего объекта A, то спросите себя, действительно ли вы являетесь владельцем B. Если нет, передайте указатель на него и предположите, что тот, кто передает указатель, отвечает за его жизненный цикл - однако это непростой путь, и, возможно, вам придется использовать указатели с реф-счетом.

Если вы хотите сделать копию B для себя, то вы можете определить метод clone() для B. Если вы хотите создать свой собственный объект, используя информацию, содержащуюся в B, то вы можете внедрить MyBFactory в конструктор и использовать его с этим B.

2
ответ дан 13 December 2019 в 19:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: