Php 单元测试异常的建议

Php 单元测试异常的建议,php,exception,phpunit,Php,Exception,Phpunit,考虑一个方法,该方法可能会引发带有一些描述性文本的异常: if ($someCondition) { throw new \Whatever\Exception('dilithium exhausted'); } 方法中的其他地方是另一个块,它可能抛出相同的异常,但文本不同: if ($anotherCondition) { throw new \Whatever\Exception('differentialator exploded'); } 在为此类编写单元测试时,您会

考虑一个方法,该方法可能会引发带有一些描述性文本的异常:

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) 为每个错误案例创建一个单独的异常(例如,\whater\dilitiumexception和\whater\differenticatorexception),然后为每个错误案例使用@exceptionExpected

我目前正在使用B,但倾向于C。我很好奇其他人在这个场景中做了什么。您是否有任何指导原则可以帮助您确定,“在什么情况下,错误应该拥有自己的异常类,而不是更通用的共享类?”

以上所有内容

A很好,我尽可能多地使用它,因为它最简单。另一种情况是A不起作用:

/**
 * @exceptionExpected FooException
 */
test() {
  // code that could throw FooException
  ...
  // purpose of the test that throws of FooException
}
在这种情况下,测试可能会在应该失败的时候通过,因为它甚至没有达到我正在测试的目标。处理这个问题的一个好方法是使用$this->setExpectedException()

当您实际可能使用来自异常的信息时,B是非常好的。我宁愿使用代码,而不是使用异常消息的文本。我有一个表单验证异常,它将数据中遇到的所有问题打包成一个异常。通过扩展exception类,可以很容易地将大量信息从内部错误状态传输到外部处理代码

C完成了与B相同的任务,但允许通过依赖更多的类来简化代码。这两者之间的区别是微妙的,我倾向于依靠设计美学来做出决定

TL;DR:使用异常代码而不是消息,并根据用例而不是单元测试进行设计。

以上所有内容

A很好,我尽可能多地使用它,因为它最简单。另一种情况是A不起作用:

/**
 * @exceptionExpected FooException
 */
test() {
  // code that could throw FooException
  ...
  // purpose of the test that throws of FooException
}
在这种情况下,测试可能会在应该失败的时候通过,因为它甚至没有达到我正在测试的目标。处理这个问题的一个好方法是使用$this->setExpectedException()

当您实际可能使用来自异常的信息时,B是非常好的。我宁愿使用代码,而不是使用异常消息的文本。我有一个表单验证异常,它将数据中遇到的所有问题打包成一个异常。通过扩展exception类,可以很容易地将大量信息从内部错误状态传输到外部处理代码

C完成了与B相同的任务,但允许通过依赖更多的类来简化代码。这两者之间的区别是微妙的,我倾向于依靠设计美学来做出决定


TL;DR:使用异常代码而不是消息,并根据用例而不是单元测试进行设计。

PHPUnit还提供
@expectedExceptionCode
@expectedExceptionMessage
,当您需要此详细级别时警告:后者需要前者


顺便说一句,我也倾向于A。如果我需要在异常中表达更多的含义,我更喜欢创建一个新的异常类。我发现消息太不稳定,不值得在大多数应用程序中进行测试。

PHPUnit还提供了
@expectedExceptionCode
@expectedExceptionMessage
,当您需要此级别的详细信息时警告:后者需要前者


顺便说一句,我也倾向于A。如果我需要在异常中表达更多的含义,我更喜欢创建一个新的异常类。我发现消息太不稳定,不值得在大多数应用程序中测试。

太好了,我完全忘记了异常代码,这太完美了。谢谢。啊,太好了,我完全忘记了异常代码,太好了。谢谢