Я пытаюсь ознакомиться с модульным тестированием в PHP с небольшим API в Lumen. Написание первых нескольких тестов было довольно приятно с помощью некоторых учебных пособий, но теперь я столкнулся с моментом, когда мне нужно смоделировать / заглушить зависимость.
Мой контроллер зависит от указанного c пользовательского типа интерфейса, на который намекают конструктор.
Конечно, я определил привязку интерфейса / реализации в ServiceProvider.
public function __construct(CustomValidatorContract $validator)
{
// App\Contracts\CustomValidatorContract
$this->validator = $validator;
}
public function resize(Request $request)
{
// Illuminate\Contracts\Validation\Validator
$validation = $this->validator->validate($request->all());
if ($validation->fails()) {
$response = array_merge(
$validation
->errors() // Illuminate\Support\MessageBag
->toArray(),
['error' => 'Invalid request data.']
);
// response is global helper
return response()->json($response, 400, ['Content-Type' => 'application/json']);
}
}
Как видите, у моего CustomValidatorContract
есть метод validate()
, который возвращает экземпляр Illuminate\Contracts\Validation\Validator
(результат проверки). Это в свою очередь возвращает экземпляр Illuminate\Support\MessageBag
при вызове errors()
. MessageBag
тогда имеет toArray()
-метод.
Теперь я хочу проверить поведение моего контроллера в случае сбоя проверки.
/** @test */
public function failing_validation_returns_400()
{
$EmptyErrorMessageBag = $this->createMock(MessageBag::class);
$EmptyErrorMessageBag
->expects($this->any())
->method('toArray')
->willReturn(array());
/** @var ValidationResult&\PHPUnit\Framework\MockObject\MockObject $AlwaysFailsTrueValidationResult */
$AlwaysFailsTrueValidationResult = $this->createStub(ValidationResult::class);
$AlwaysFailsTrueValidationResult
->expects($this->atLeastOnce())
->method('fails')
->willReturn(true);
$AlwaysFailsTrueValidationResult
->expects($this->atLeastOnce())
->method('errors')
->willReturn($EmptyErrorMessageBag);
/** @var Validator&\PHPUnit\Framework\MockObject\MockObject $CustomValidatorAlwaysFailsTrue */
$CustomValidatorAlwaysFailsTrue = $this->createStub(Validator::class);
$CustomValidatorAlwaysFailsTrue
->expects($this->once())
->method('validate')
->willReturn($AlwaysFailsTrueValidationResult);
$controller = new ImageResizeController($CustomValidatorAlwaysFailsTrue);
$response = $controller->resize(new Request);
$this->assertEquals(400, $response->status());
$this->assertEquals(
'application/json',
$response->headers->get('Content-Type')
);
$this->assertJson($response->getContent());
$response = json_decode($response->getContent(), true);
$this->assertArrayHasKey('error', $response);
}
Это тест, который работает нормально - но может кто-нибудь сказать мне, если есть лучший способ написать это? Это не правильно. Нужен ли этот большой стек mo c -объектов из-за того, что я использую фреймворк в фоновом режиме? Или что-то не так с моей архитектурой, так что это кажется слишком "сверхмощным"?
Спасибо