【问题标题】:Is using Assert.assertTrue(true); and assert Assert.fail(); good practise in JUnit testing?正在使用 Assert.assertTrue(true);并断言 Assert.fail(); JUnit 测试的好习惯?
【发布时间】:2016-04-20 09:05:36
【问题描述】:

这是使用 Assert.assertTrue(true); 的好习惯还是坏习惯;和 JUnit 测试中的 Assert.fail() 以及为什么?

我知道还有规则 @Test (expected = Exception.class),但是你可以有不止一个异常可以在测试方法上引发,如果你不想为一种测试方法拥有无数测试方法,这个可能是选项。

用例是这样的: 您测试的方法可以引发零个、一个或多个异常(例如,为了简单起见只有一个),并且您想测试调用是好的,所以不应该引发异常,如果你进入 catch 块,你将引发 Assert.fail();那么你想要测试用例什么时候应该引发异常,所以你在 catch 块中调用 Assert.assertTrue(true);说“是的,这就是我想要的”。从测试中,您可以在一种测试方法中看到它何时应该失败,以及当您运行测试时,它是否真的表现得像您想要的那样。
问题是:这是好还是坏的做法?为什么?

public void fooMethod(boolean paramenter) {
  if(false) {
    throw new Exception();
  }
}

@Test
public void testFooMethod() {

  try {
     myTestedClassMock.fooMethod(true); //should not raise exception
  } catch(Exception e) {
    Assert.fail();
  }  

  try {
    myTestedClassMock.fooMethod(false); //should raise exception
  } catch (Exception e) {
     Assert.assertTrue(true);
  }

}

【问题讨论】:

  • 这在programmers.se 上可能会更好,但我看不出断言真实的意义,您可以只写一条评论说“预期”,这可能同样清楚。
  • 我个人认为这是不好的做法,对于您的用例,我会编写两个测试方法并适当地命名。如果您有两个例外,那么我希望有三种测试方法。这样你就必须编写更多的测试方法,但你会得到更干净的测试代码,并且意图可以更好地传达(通过方法名称)。
  • 学习使用ExpectedException 类。它取代了您所描述的技术以及其中一个答案中给出的基于注释的技术。
  • 我知道 ExpectedException,我在我的问题中提到了它。但是如果你的课程有 20 个或更多的方法,并且所有的都有 4 个测试用例,那真的会很混乱。 (我说的是控制器的应用逻辑类,这就是方法这么多的原因,测试类有40个方法没问题..)
  • 不,您没有在问题中提到 ExpectedException 类。如果你学会使用它,这一切都会变得简单得多。我不是在谈论注释 - 注释现在已经过时了。

标签: java unit-testing junit assertion


【解决方案1】:

您始终可以省略Assert.assertTrue(true),因为assertTrue 是为不同的目的而设计的。它可以检查涉及多个布尔项的一般条件,例如

Assert.assertTrue(t == null ||| minSize < 0 || t.size() > minSize);

断言一个常量true 总是成功的,没有任何痕迹,所以你可以从你的代码中完全删除这一行。通过将Assert.fail(); 放置在必须抛出异常的测试代码行之后立即捕获抛出预期异常的情况,并带有指示未引发预期异常的消息。

如果您不想为一种测试方法提供无数测试方法,这可能是一种选择。

通常,“无数种测试方法”是更好的选择。作为替代方案,您可以在测试中捕获 ExceptionRuntimeException,而不是捕获每个单独的异常。这在生产代码中是一个值得商榷的做法,但在测试代码中,当您必须确保不抛出异常时,它绝对没问题。

但是,拥有Assert.fail(); 并不是一个不常见的快捷方式,而且通常也是可以接受的。添加一条描述失败原因的消息是一个好主意,这样维护您的代码的人就不必通读您的测试来查看发生了什么。当您捕获异常时,它的消息很适合作为测试失败消息的候选者。

【讨论】:

  • 如果您有 MVC 应用程序并且您正在测试具有从控制器调用的方法的应用程序逻辑类,这也是更好的选择吗?这个测试类可以有 3-4 种方法,也可以有 20-40 种,这取决于具体情况。因此,如果您对每种测试方法都有多个测试方法,那可能会非常混乱。谢谢
  • 我想说:在一个类上拥有 20 到 40 个方法已经有一定的“恶臭”了。
  • 我个人不会打电话给Assert.fail() 没有可接受的参数。尤其是当有可用作消息的信息异常时。
  • @VGR 非常感谢您的评论!这很有意义,我编辑了答案以反映这一点。
【解决方案2】:

使用fail() 是一个好习惯,但不像你那样做。那是因为如果发生异常,您想让测试失败。您可以在不捕获此异常的情况下执行此操作。如果出现,则测试失败。

在第二种情况下,不要使用assertTrue(true),而是在方法调用之后添加fail()

myTestedClassMock.fooMethod(true); //should not raise exception

try {
    myTestedClassMock.fooMethod(false); //should raise exception
    Assert.fail("Exception expected!");
} catch (Exception e) {
    // exception handling
}

这让你的意图更加清晰,如果没有抛出异常,你会看到测试失败。

【讨论】:

  • 谢谢,但在第一种情况下,您必须在 try - catch 块中也有该方法,否则您的编译器会像婴儿一样哭泣 - 看看它在它的主体中抛出的 fooMethod 的定义,所以你有通过尝试捕获或抛出方法名称以某种方式在测试中处理
  • 不一定:可以在测试方法的定义中加入throws声明。它不会改变测试的任何有用性。这将是我的选择。
  • 是的,那就没问题了=)
【解决方案3】:

第二种情况有什么遗漏吗? 我宁愿做下一次检查:

  try {
    myTestedClassMock.fooMethod(false);
    Assert.fail("should raise exception");
  } catch (Exception e) {
    //Check if this is the exception you expected
  }

第一种情况呢,如果会抛出异常,无论如何都会测试失败,所以不需要Assert.fail()try-catch

【讨论】:

    【解决方案4】:

    关于您的源代码的一些良好做法。

    首先:每个测试方法中只有一个断言。因此,当该方法失败时,您会立即知道该去哪里。

    这也有助于解决您的问题:

    @Test
    public void testFooMethodThatShouldNotThrow() throws WhatEverException {
       bar.foo(true)
    

    因此,如果 foo() 抛出上述代码,则单元测试失败。我们添加了一个 throws 子句并不重要。

    当您期望抛出异常时;那就这么说吧:

    @Test(expected=WhateverException.class)
    public void testFooMethodThatShouldThrow() {
      bar.foo(false);
    }
    

    如果要检查抛出异常的某些属性;那么你会做一个

    @Test
    public void bla {
      try {
        bar.foo();
        fail("should have thrown");
      catch (WhateverException e) {
        assertThat(e.getMessage(), is("bla blub flubber"));
      }
    

    例如。

    最后:确实需要一个 assertThat:assertThat。忘记所有其他人;并学会使用那个。

    【讨论】:

      猜你喜欢
      • 2017-03-09
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多