PHPUnit:对 return 特定类型使用注解真的有必要吗?
PHPUnit: Is using annotations to return a specific type really necessary?
我正在尝试通过 API 在 Lumen 中熟悉 PHP 中的单元测试。
在一些教程的帮助下编写前几个测试非常好,但现在我遇到了一个问题,我必须模拟/存根一个依赖项。
我的控制器依赖于构造函数中提示的特定自定义接口类型。
当然,我在 ServiceProvider.
中定义了这个 interface/implementation-binding
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()
,其中 returns 是 Illuminate\Contracts\Validation\Validator
的一个实例(验证结果)。当调用 errors()
时,这又是 returns Illuminate\Support\MessageBag
的一个实例。 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);
}
虽然经过一天的研究后这个测试是有效的,但我很确定我在这里遗漏了一些非常重要的东西。 None 我看过的教程中提到,注释对于确保模拟的对象类型是特定类型是必需的。最终,这是我完成这项工作的唯一方法。
我还放弃了创建实际的 double 类 并尝试使用内置功能即时制作它们。但我知道可能性是存在的。
如果您能给我一个建议,如果这至少接近预期的测试方法,我将不胜感激。
如果我必须处理特定的对象类型,我真的必须写注释吗?
是不是我的架构还有什么问题,所以感觉如此"overengineered"?
好的,我很确定 PHPUnit 抛出了一个错误,因为传递给控制器的类型错误。其实,这是另外一回事。
这些注解只需要满足关于 getStub()
或 getMock()
方法的 return 类型的 Intelephense。
即使没有注释,测试也是运行没有任何错误。
我正在尝试通过 API 在 Lumen 中熟悉 PHP 中的单元测试。 在一些教程的帮助下编写前几个测试非常好,但现在我遇到了一个问题,我必须模拟/存根一个依赖项。
我的控制器依赖于构造函数中提示的特定自定义接口类型。
当然,我在 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()
,其中 returns 是 Illuminate\Contracts\Validation\Validator
的一个实例(验证结果)。当调用 errors()
时,这又是 returns Illuminate\Support\MessageBag
的一个实例。 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);
}
虽然经过一天的研究后这个测试是有效的,但我很确定我在这里遗漏了一些非常重要的东西。 None 我看过的教程中提到,注释对于确保模拟的对象类型是特定类型是必需的。最终,这是我完成这项工作的唯一方法。 我还放弃了创建实际的 double 类 并尝试使用内置功能即时制作它们。但我知道可能性是存在的。
如果您能给我一个建议,如果这至少接近预期的测试方法,我将不胜感激。
如果我必须处理特定的对象类型,我真的必须写注释吗?
是不是我的架构还有什么问题,所以感觉如此"overengineered"?
好的,我很确定 PHPUnit 抛出了一个错误,因为传递给控制器的类型错误。其实,这是另外一回事。
这些注解只需要满足关于 getStub()
或 getMock()
方法的 return 类型的 Intelephense。
即使没有注释,测试也是运行没有任何错误。