Как обеспечить изоляцию в Unit тестах

156
15 апреля 2022, 13:20

Пытаюсь написать Unit тест "по всем правилам"...и не могу понять как я могу обеспечить изоляцию тестируемого класса от других.

public class ColumnDivision {
        private final DivisionStep mainDivision;
        private final List<DivisionStep> listDivisions;
    public ColumnDivision(DivisionStep mainDivision) {
        this.mainDivision = mainDivision;
        this.listDivisions = new ArrayList<>();
    }
    public DivisionStep getMainDivision() {
        return mainDivision;
    }
    public List<DivisionStep> getListDivisions() {
        return listDivisions;
    }
    public void createColumn() {
        int intermediateRemainder = this.mainDivision.getX();
        int y = this.mainDivision.getY();
        int remainder = this.mainDivision.getRemainder();
        while (intermediateRemainder != remainder) {
            int nextDividend = takeNextDivident(intermediateRemainder, y);
            DivisionStep d = new DivisionStep(nextDividend, y);
            this.listDivisions.add(d);
            intermediateRemainder = takeIntermediateRemainder(intermediateRemainder, d);
        }
    }
//private методы

Мне нужно обеспечить изоляцию от класса DivisionStep. Да я могу создать mock и передать его в конструктор. Но в дальнейшем всё равно будет создание реальных объектов класса DivisionStep. И, по факту, ни какой изоляции не будет.

Это криво написанный код, который не протестировать? Или есть способ обеспечить изоляцию? Или передать mock объект в конструкторе и этого достаточно?

Спасибо за советы)

Answer 1

Во-первых, нужно понять действительно ли стоит и нужно тестировать ColumnDivision обособленно. На этот вопрос однозначно ответить сложно, так как это зависит от того, как распределены обязанности между ColumnDivision и DivisionStep, что именно делают оба класса, насколько их поведение связано, является DivisionStep частью внутренней реализации ColumnDivision или все же это самостоятельная сущность.

Во многих случаях, будет более полезно все же тестировать логику ColumnDivision используя DivisionStep (который в свою очередь может быть протестирован отдельно своими тестами).

Конечно ошибки и проблемы в DivisionStep могут привести к ложнопозитивным ошибкам в тестах ColumnDivision, но с другой стороны, полная изоляция усложняет взаимодействие между ColumnDivision и DivisionStep, так же усложняет сам тест. А значит и вероятность того, что в сам тест закрадется ошибка и тесты по отдельности будут работать, а при интеграции что-то сломается. Конечно должны быть интеграционные тесты, но во-первых они по определению не будут изолированны, а во-вторых, в них обычно далеко не все покрывается.

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

Но если все же аргументы не использовать перевешивают, то тогда можно изолироваться. Основная проблема это создания новых экземпляров DivisionStep. Чтобы в тесте можно было это конфигурировать, создайте DivistionStepFactory (java.util.function.Supplier тоже подойдет) и ее передавайте ColumnDivision, как зависимость. В боевом режиме будет использована одна реализация фабрики и там будут создаваться реальные DivisionStep-ы, а в тестах можно подсунуть другую реализацию, которая будет создавать то, что нужно в конкретном тесте.

READ ALSO
Как в spring обработать body в виде json?

Как в spring обработать body в виде json?

Пытаюсь изучить api в springGET Запрос хорошо посылается, а вот POST пока сложно

201
Вывод двумерного массива. Java

Вывод двумерного массива. Java

Создал новый метод, прописал там следующее:

100
Не могу открыть файл для работы в Apache POI

Не могу открыть файл для работы в Apache POI

Необходимо прочитать файл и распарсить его с помощью Apache POIФайл открывается нормально, но при попытке создать WorkBook кидает исключение

172
java сравнение дат

java сравнение дат

Подскажите какие существуют варианты сравнения текущей даты и, например, даты окончания срока действия сертификатаНеобходимо построить...

325