java - 损坏的单元测试的语义

标签 java unit-testing junit

我正在为我们的主要产品编写单元测试并且有一个问题:如何区分

  • 失败的测试是因为他们测试的东西出错了(例如发现了一个错误并且它是一个非回归测试)
  • 由于测试的另一个意外部分失败而失败的测试(因为测试错误或出现未知错误)

对于第一个,我们肯定有 jUnit Assert 框架,但是对于第二个我们有什么?

示例:我的单元测试正在测试 c() 不会抛出 MyException,但要执行 c(),我需要先执行 a(),然后执行 b(),两者都可以抛出 MyException(),所以我会写:

@Test
public void testC() {
  a();
  Object forC = b();
  try {
    c(forC);
  } catch (MyException e) {
    Assert.fail("....");
  }
}

但接下来我需要处理可能由 a 或 b 抛出的 MyException,还要处理 forC 不应该为 null 的事实。执行此操作的最佳方法是什么?

  • 捕获由 a 或 b 抛出的 MyException 和 Assert.fail,但 a 和 b 未通过此测试进行测试,因此对我而言,当它们失败时不应将它们标记为测试失败。也许他们稍后会失败,因为此时我们应该做 b();a() 而不是 a();b();。
  • 让 testC 抛出 MyException,这样测试就会失败并显示“MyException”,但这是一种误导,因为 MyException 不会告诉测试写错了。然后所有测试都将失败,每个测试都有自己的异常。在这种情况下,如果 forC 为 null,我还需要抛出 NullPointerException 之类的东西,这也没有语义。
  • 捕获 a 和 b 抛出的 MyException 并将其包装成一个异常,告知测试可能有误,例如 TestCorruptedException。但是我在 jUnit 中找不到这样的异常,所以它们不会被 jUnit 识别(这对我来说没问题)。我还需要从我所有的单元测试中知道这个异常,这些单元测试当然分为多个模块、项目等等……所以这是可行的,但会增加依赖性。

您将如何解决这个问题?我可能会选择第二个,但如上所述我对此并不满意。

最佳答案

单元测试的基石是测试所需的最少代码量,否则它可能会落入您正在寻找端到端功能的集成测试空间。

如果你能证明 a() 可以在它自己的测试类中创建和测试,并且 b() 也可以在它自己的测试类中创建和测试测试类,那么您上面的测试可以忽略 a()b() 的测试,而是使用不会失败的已知值。这通常通过使用 mock objects 来满足。 .

通过将 a() 和 b() 创建为模拟对象,c() 可以单独进行测试。如果您发现无法在隔离 a() 和 b() 的情况下测试 c(),那么这表明您的代码需要更改,以便分离关注点。这通常由 injecting the dependany 满足a() 和 b() 转化为 c()。

这篇文章在 when to use mock objects in unit testing可能有助于进一步阐明该主题。

关于java - 损坏的单元测试的语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11474063/

相关文章:

Java try catch 最后似乎毫无意义

java - 静态类非静态成员

Java 堆大小减少

java - java中的while循环除以二

c++ - Boost.Test 错误消息不再显示在 VS2010 的错误列表中

java - 如何对无效且不带任何参数的方法进行单元测试?

c# - 在单元测试中等待异步事件引发事件

c# - 使用伪造的 HTTPContext 对 ASP.NET Web API Controller 进行单元测试

java - 具有抛出异常的 block 的代码覆盖率

java - Mockito 中的连续通话测试