Когда вы используете композицию, вы можете высмеивать другие объекты, из которых зависит ваш класс под тестом, но когда вы используете наследование, вы не можете издеваться над базовым классом. (Или вы можете?)
Обычно я стараюсь отдать предпочтение композиции над наследованием , но иногда наследование действительно кажется лучшим инструментом для работы – ну, по крайней мере, до тех пор, пока не дойдет до модульного тестирования.
Итак, как вы проверяете наследование? Или вы просто уничтожаете его как непроверяемый и используете композицию вместо этого?
Примечание. В основном я использую PHP и PHPUnit, поэтому помощь с этой стороны наиболее ценится. Но было бы также интересно узнать, есть ли решения этой проблемы на других языках.
Используйте набор модульных тестов, которые отражают иерархию классов. Если у вас есть базовый класс Base и производный класс Derived, то есть тестовые классы BaseTests и производные от этого DerivedTests. BaseTests отвечает за тестирование всего, что определено в Base. DerivedTests наследует эти тесты и также отвечает за тестирование всего в Derived.
Если вы хотите протестировать защищенные виртуальные методы в Base (т.е. интерфейс между базой и его дочерними классами), может также иметь смысл создать тестовый только производный класс, который проверяет этот интерфейс.
Пока вы не переопределяете общедоступные методы родительского класса, я не понимаю, зачем вам их тестировать во всех подклассах этого класса. Модуль тестирует методы родительского класса и проверяет только новые методы или переопределенные в подклассах.
Причина, по которой вы используете макетные объекты в композиции, – это то, что реальные объекты делают то, что вы не хотите настраивать (например, использовать сокеты, последовательные порты, получать пользовательский ввод, извлекать громоздкие данные и т. Д.). Вы всегда должны использовать реальные объекты там, где это возможно. Макетные объекты предназначены только тогда, когда предполагаемая попытка реализовать и поддерживать тест с использованием реального объекта больше, чем для реализации и поддержания теста с использованием макетного объекта. Ваш базовый класс не должен делать ничего такого, как это!
Поэтому вам не нужно проверять наследование. Предположительно, вы используете поведение базового класса, поэтому просто проверяйте производный класс, как обычно, – методы вызова как базового, так и производного классов, подходящего для теста. Это гарантирует, что все предполагаемое поведение производного класса будет проверено.
По сути, (большую часть времени) вы проверяете производный класс, как будто базовый класс невидим.
Почему вы должны издеваться над базовым классом?
Как вы можете создавать производные классы из несуществующего родительского класса?
Просто проверьте его как обычно, но родительский класс.
Думаю, вы не рассказали всю историю.
Кроме того, функции языка якобы работают (если вы не работаете с бета-версиями или так), поэтому вам не нужно проверять, действительно ли метод существует в производном классе.
Нет, нет. Вам просто нужно проверить, что методы overriden делают то, что им нужно. Он должен в NO WAY влиять на поведение ваших родительских методов. Если ваши родительские методы начинают сбой, значит, вы пропустили связанные условия при тестировании на родительском уровне.