考虑一个可能会抛出一些带有描述性文本的异常的方法:
if ($someCondition) {
throw new \Whatever\Exception('dilithium exhausted');
}
该方法的其他地方是另一个可能抛出相同异常的块,但文本不同:
if ($anotherCondition) {
throw new \Whatever\Exception('differentialator exploded');
}
在为此类编写单元测试时,您会创建失败案例,以便您可以验证是否正确抛出了这两个异常。在这些失败案例中,您更愿意:
A)在测试方法的docblock中使用@exceptionExpected来捕获泛型\ Whatever \ Exception类,然后忽略getMessage()文本,假设你得到了正确的文本? (似乎是个坏主意。)
或:
B)使用try / catch然后断言捕获的异常的getMessage()文本等于你期望的确切描述性字符串? (更有弹性,但这意味着每当您更改错误措辞时都会更改测试。)
或:
C)为每个错误情况创建一个单独的异常(例如,\ Whatever \ DilithiumException和\ Whatever \ DifferentialatorException),然后对每个错误使用@exceptionExpected。
我目前正在使用B但是倾向于C.我很好奇其他人在同一场景中做了些什么。您是否有任何指导方针可以帮助您确定“错误在什么时候应该使用自己的异常类而不是更通用的共享类?”
答案 0 :(得分:2)
以上所有。
A很棒,我尽可能多地使用,因为它最简单。当A不起作用时,还有另一种情况:
/**
* @exceptionExpected FooException
*/
test() {
// code that could throw FooException
...
// purpose of the test that throws of FooException
}
在这种情况下,测试可能会在它失败时通过,因为它甚至没有达到我测试的水平。解决这个问题的一个好方法是使用$ this-> setExpectedException()
当您实际使用异常中的信息时,B非常棒。我宁愿使用代码,而不是使用异常消息的文本。我有一个表单验证异常,它将数据中遇到的所有问题打包成一个例外。通过扩展异常类,可以很容易地将大量信息从内部错误状态传输到外部处理代码。
C完成与B相同的操作,但允许通过依赖更多类来简化代码。这两者之间的区别是微妙的,我倾向于依靠设计美学来做出决定。
TL; DR:使用异常代码而不是消息,并设计用例而不是单元测试。
答案 1 :(得分:2)
当您需要此级别的详细信息时,PHPUnit还会提供@expectedExceptionCode
和@expectedExceptionMessage
。 警告:后者需要前者。