Я пишу класс, который наследует интерфейс. Клиентский код будет написан для этого интерфейса, а класс написан для его поддержки. Идея заключается в том, что я позже напишу другие классы для этого интерфейса, а объекты этих двух разных классов должны быть полностью взаимозаменяемыми. Вместо того, чтобы писать тестовый класс для этого первого класса, я хочу написать его для интерфейса.PHPUnit - Написание тестового класса для интерфейса и тестирование объектов с использованием фабрики
Мой план состоял в том, чтобы написать тестовый класс, который будет принимать заводский объект для конструктора (инъекция зависимостей) и использовать фабрику для создания новых экземпляров тестируемого класса.
Таким образом, если бы я хотел проверить ClassA, я мог бы передать объект ClassAFactory конструктору тестового класса, и если бы я захотел проверить ClassB, я бы передал объект ClassBFactory. Оба класса предназначены для взаимозаменяемости, и поскольку предполагается, что тестируются только общедоступные методы, это кажется идеальным.
Но как насчет тестирования конструктора? Должен ли я лучше писать абстрактный тестовый класс и внедрять тесты конструктора в классы, наследующие абстрактный тестовый класс (разные классы могут создаваться по-разному)?
Если я использовал первую идею, я думаю, я бы тестовый класс для каждого класса испытывается, как:
class ClassATest extends [PHPUnit test case]
{
$myFactory = new ClassAFactory();
$myTest = new ClassTest($myFactory);
$myTest->test1();
$myTest->test2();
//etc.
}
Что лучший способ пойти по этому поводу? Я хочу иметь общий тест, так что, когда я пишу новые классы для реализации общего интерфейса, я могу просто поставить объект тех же тестов, что и для других. Но, видя, что разные классы будут иметь разные конструкторы, возможно, лучше написать абстрактный класс тестов и расширить его для каждого нового объекта? Как вы думаете?
В этом конкретном примере классы будут представлять получателей для списка рассылки. Хотя у них будут разные способы выполнения своей работы, они будут брать те же данные от клиента и возвращать те же результаты - полностью взаимозаменяемые. Мне кажется, что если объекты из разных классов, которые используют этот интерфейс, взаимозаменяемы внутри клиентского кода, они также должны быть взаимозаменяемы в тестовом коде. Поэтому, когда я говорю, что хочу протестировать интерфейс, я имею в виду, что я хочу написать тест для этого интерфейса, чтобы протестировать класс, который использует этот интерфейс. Это имеет смысл для вас? –
Нет, это все еще не имеет смысла. Я не понимаю, как работает интерфейс. Возможно, вам нужен абстрактный базовый класс, а не интерфейс для реализации общего кода. Я не уверен, что отличается от ваших классов, кроме данных. – liquorvicar
Предположим, что в классе MailChimpRecipient использует интерфейс MailingListRecipient: клиентский код добавляет кого-то в список, задав свойства адреса электронной почты и имя объекта-получателя, а затем вызывая метод их добавления. Теперь этот метод для класса MailChimp будет использовать API MailChimp для их добавления. Скажите в будущем, я хочу разместить собственный список рассылки или использовать другого поставщика, я мог бы переключить класс на другой класс, который использует интерфейс MailingListRecipient. Этот класс может сделать что-то совершенно другое, чтобы добавить получателя, но он все равно берет те же данные. –