Как указано в комментариях, вы ошибаетесь с целью и областью применения модульного теста и интеграционного теста , и отсюда возникает путаница.Начнем с вашего «теста»:
/** @test */
public function the_user_can_update_his_profile()
{
$response = $this->json('POST', route('register_user'), ['email' => 'email@email.com', 'password' => 'password123']);
$userRepository = app(UserRepository::class);
$user = $userRepository->find($response['userId']);
// ACT
// ASSERT
}
Это интеграционный тест.Вы тестируете «удаленный» маршрут (хорошо, он внутренний, но вы все еще тестируете каждый отдельный компонент на своем пути).Интеграционный тест идеально подходит для подтверждения того, что бизнес-логика была реализована правильно и что маршрут ведет себя как ожидалось;он проходит свой путь от начала до завершения, тестируя каждое взаимодействие между компонентами и логикой в контроллере + представление непосредственно.
Это все хорошо и хорошо, но на самом деле это нам не очень помогает.Мы все еще слепы в отношении тестируемости самих компонентов.Вот где начинается модульное тестирование.
Предположим, у вас есть класс следующим образом:
<?php
class Foo {
public $value = 0;
public function __construct($value) {
$this->value = (int)$value;
}
public function getRemainder(int $item) {
return $this->value % $item;
}
}
Вы вполне можете использовать этот класс в одном из ваших контроллеров;смысл модульного тестирования состоит в том, чтобы утверждать, что:
- конструктор сохраняет правильное значение (в виде целого числа)
- метод
isModulo
делает то, что написано на банке.
Для этого мы можем написать следующий тест:
public function isActualModuloClass() {
$modulo = new Foo(5);
$modulo_float = new Foo(2.3);
assert($modulo->value == 5, "Integer modulo constructor works");
assert($modulo_float->value == 2, "Float modulo casts to integer properly");
assert($modulo->getRemainder(5) == 0, "Modulo 5%5 is 0");
assert($modulo->getRemainder(4) == 1, "Modulo 5%4 is 1");
}
И, конечно же, мы провериликаждый метод, каждая ветвь нашего компонента в изоляции .Это модульный тест.
Он усложняется с классами, которые взаимодействуют с другими объектами, но при правильной структуре очень легко использовать инструменты для вставки фиктивных копий объектов, чтобы иметь возможность заглушить взаимодействия,Когда ваш код затрагивает сразу несколько вещей нечистым образом, ваши тесты, как правило, приводят к ужасному беспорядку.
Обсуждение, которое вы связали, касается этих тестов и способов сделать их не хрупким беспорядком, который оникак правило, в плохо продуманных кодовых базах.Теоретически, автор также прав: вы начинаете с объектов без зависимостей, тестируете их, затем постепенно повышаетесь, предполагая, что контракты , устанавливаемые ими, являются нормальными и проверенными, и вы продвигаетесь вверх по пирамиде.,На практике это очень трудно сделать, когда код написан с тестированием в качестве запоздалой мысли.