Можно ли тестировать абстрактный класс модульно, создавая его как фиктивный объект? - PullRequest
6 голосов
/ 12 апреля 2011

До меня дошло, что вы можете протестировать абстрактный класс модульно, создав его экземпляр как фиктивный объект.Тем самым вы высмеиваете абстрактные свойства и методы, и в то же время можете протестировать реализованные.

Однако я привык различать класс для проверки и введенные зависимости для макета / заглушки .Итак, на этой ранней стадии моего нового просветления я задаюсь вопросом, есть ли какие-либо подводные камни в этом способе тестирования?Есть мысли по этому поводу?

С уважением, Мортен

Ответы [ 5 ]

10 голосов
/ 12 апреля 2011

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

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

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

Конечно, я могу думать о случаях (с унаследованным кодом), когда основной проблемой являетсяуметь писать юнит-тесты каким-либо образом, чтобы включить рефакторинг (как описано в Эффективная работа с устаревшим кодом ).В качестве временного решения в таких случаях (почти) все идет.Но после того, как модульные тесты сработают, класс должен быть реорганизован как можно скорее, чтобы сделать его чистым и тестируемым (и его модульные тесты тоже, чтобы сделать их ремонтопригодными).

3 голосов
/ 12 апреля 2011

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

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

3 голосов
/ 12 апреля 2011

Вместо использования наследования для объединения двух классов, посмотрите, можно ли использовать композицию.

Вместо этого:

abstract class PaySalary {
    payAmount(decimal money) {
        if (transferAmount(money)) {
            isPaid = true;
        }
    }

    abstract void transferAmount(decimal money);
}

Сделайте следующее:

class PaySalary {
    public MoneyTransferrer;

    payAmount(decimal money) {
        if (MoneyTransferrer.transferAmount(money)) {
            isPaid = true;
        }
    }
}

Таким образом, вам не нужно наследовать класс в вашем модульном тесте, но вы можете просто издеваться над MoneyTransferrer.Вы также можете протестировать MoneyTransferrer вне зависимости от базового класса.

0 голосов
/ 04 октября 2018

Да, вы будете тестировать абстрактный класс так же, как тестируете интерфейс с инжекцией.

Если вы пишете тест для ILog и внедряете его для тестирования с использованием MockLog, то вы делаете то же самое для LogBase (в данном примере это абстрактный класс) и внедряете его с MockLog только так же.

abstract class НЕ является interface, НО они используются почти так же, как накладные расходы.

0 голосов
/ 12 апреля 2011

абстрактный класс по определению абстрактный. Не должно быть ничего, чтобы проверить, действительно ли это абстрактно.

...