Я новичок в тестировании, и я не уверен, что поступил правильно:
Я хочу не выполнять модульное тестирование для определенного класса, но для любого класса, разрешенного из моего контейнера ioc. В контейнере ioc я связываю свои интерфейсы с конкретными классами, например так:
Пример (я использую Laravel 5):
// in a service provider
public function register(){
$this->app->bind('FooInterface', function() {
return new SomeConcreteFoo;
});
}
Тогда я хочу написать модульный тест против FooInterface
и не SomeConcreteFoo
который может быть заменен другим классом позже.
Причина, по которой я хочу это сделать, заключается в том, что мне кажется, что соответствующее тестирование должно быть нацелено на то, что возвращает мой ioc-контейнер, поскольку именно это я буду использовать в приложении. Мне также кажется, что тестирование должно проводиться на уровне интерфейса, поскольку именно здесь я определяю ожидания, которые остальная часть приложения будет относиться к моему классу.
Мне трудно найти какую-либо информацию о том, как это сделать, что наводит меня на мысль, что я могу думать об этом неправильно. Например, возможно, то, что я пытаюсь выполнить, больше похоже на интеграционный тест, а не на модульный тест.
Итак, первый вопрос: я думаю о том, чтобы проверить это правильно? на случай, если я не … Есть ли у вас какие-либо предложения относительно лучшей практики для альтернативного пути тестирования?
Второй вопрос: если мои мысли верны — как настроить phpspec для использования контейнера IOC Laravel, чтобы я мог проверять все, что возвращает IOC …
Я хочу не выполнять модульное тестирование для определенного класса, но для любого класса, разрешенного из моего контейнера ioc. В контейнере ioc я связываю свои интерфейсы с конкретными классами, например […]
Это не то, как написаны юнит-тесты. Модульное тестирование — это описание поведения класса в отдельности, поэтому единственный реально созданный объект — это тестируемый класс (а иногда и простые объекты значений).
Затем я хочу написать модульный тест для FooInterface, а не SomeConcreteFoo, который может быть заменен другим классом на более позднем этапе.
Это действительно то, как вы должны написать свои модульные тесты. Предпочитаю интерфейсы для соавторов.
Каждый фреймворк поддерживает эту функцию и создаст для вас двойные тесты, не заставляя вас предоставлять конкретные реализации.
class BarSpec extends ObjectBehavior
{
function it_does_amazing_things(FooInterface $foo)
{
$results = ['a', 'b', 'c'];
$foo->find('something')->willReturn($results);
$this->findMeSometing()->shouldReturn($results);
}
}
В этом конкретном примере PhpSpec будет использовать Prophecy (его насмешливую структуру), чтобы создать двойной тест FooInterface
и вставит его в метод примера. То, что вы делаете с этим объектом, определяет, подделка ли это, заглушка или издевательство.
Причина, по которой я хочу это сделать, заключается в том, что мне кажется, что соответствующее тестирование должно быть нацелено на то, что возвращает мой ioc-контейнер, поскольку именно это я буду использовать в приложении.
Как объяснялось выше, модульные тесты фокусируются на поведении одного класса. Его сотрудники обычно фальсифицированы. Это по нескольким причинам. Одним из них является скорость. Еще один отзыв. Если тест не пройден, мы получим четкую обратную связь о том, какой класс нарушен. Если бы вы создавали всех соавторов, вместо использования двойников теста, одна ошибка могла бы сделать весь ваш набор тестов красным. Я даже не буду упоминать, насколько сложно будет поддерживать и создавать все необходимые объекты (хотя здесь могут помочь контейнеры).
Помните, что написание юнит-тестов — это скорее проектная деятельность, а не тестирование.
Например, возможно, то, что я пытаюсь выполнить, больше похоже на интеграционный тест, а не на модульный тест.
В самом деле. Узнайте больше о тестовой пирамиде. Большинство ваших тестов должны быть юнит-тестами. Затем у вас должно быть несколько интеграционных и приемочных тестов, в которых можно было бы использовать более одного класса одновременно. Причина, по которой вам нужно больше модульных тестов, чем интеграционных, состоит в том, что последние более хрупкие и их сложнее поддерживать / изменять.
Используйте PHPUnit для интеграционных тестов. PhpSpec не подходит для этой работы. PhpSpec отлично подходит для разработки ваших классов (написания юнит-тестов), особенно если вы делаете это сначала в тестовом режиме.
Второй вопрос: если мои мысли верны — как настроить phpspec для использования контейнера IOC Laravel, чтобы я мог проверять все, что возвращает IOC …
Вы не Вы можете подумать об использовании контейнера в интеграционных тестах.
Некоторое чтение:
Других решений пока нет …