PHPUnit 如何实现包含前序异常、自定义属性的异常对象全量比对
目前PHPUnit原生尚未内置支持全量比对异常对象的断言方法,你可以通过自定义封装辅助方法的方式实现你要的简洁调用效果,同时兼顾全量属性比对和自动异常捕获的能力。
方案1:封装测试基类/Trait,调用逻辑和原生expectException对齐
trait FullExceptionAssertTrait { /** * 断言会抛出和预期对象完全一致的异常 * @param \Throwable $expected 预期异常对象 * @param bool $strict 是否使用引用一致性校验(assertSame) */ public function expectFullException(\Throwable $expected, bool $strict = false): void { $this->registerCallback(function () use ($expected, $strict) { $actual = $this->status->getException(); if (!$actual) { $this->fail('Expected exception was not thrown'); } $strict ? $this->assertSame($expected, $actual) : $this->assertEquals($expected, $actual); }); } }
调用方式和原生方法完全一致:
public function testControllerThrowsCorrectException() { $previousException = new \RuntimeException('underlying error'); $expected = new BadRequestException('sample-error-code', $previousException); // 仅需一行断言,后续代码抛出的异常会自动比对全量属性 $this->expectFullException($expected); $controller->get(); }
方案2:闭包传入待执行代码,更直观的单行调用
如果不需要和原生调用逻辑对齐,也可以用闭包封装,直接在同一个调用里传入待执行代码:
trait FullExceptionAssertTrait { public function assertThrows(\Throwable $expected, callable $run, bool $strict = false): void { try { $run(); $this->fail('No exception was thrown'); } catch (\Throwable $actual) { $strict ? $this->assertSame($expected, $actual) : $this->assertEquals($expected, $actual); } } }
调用时一行即可完成所有逻辑:
$this->assertThrows(new BadRequestException('sample-error-code', $previousException), fn() => $controller->get());
相关说明
截止到PHPUnit 10稳定版,官方尚未将全量异常比对功能纳入核心开发规划,上述自定义封装方案是目前社区通用的解决方案,不需要额外依赖,同时完全覆盖需求:会自动比对异常的所有属性,包括前序异常、自定义私有属性、异常类、消息、错误码等所有内容。
内容的提问来源于stack exchange,提问作者ChristiaanB
相关产品推荐
相关产品推荐

