正在使用 Assert.assertTrue(true);并断言 Assert.fail(); JUnit 测试的良好实践?

Is using Assert.assertTrue(true); and assert Assert.fail(); good practise in JUnit testing?

这种使用 Assert.assertTrue(true) 的做法是好是坏?和 Assert.fail() 在 JUnit 测试中,为什么?

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

用例是这样的: 您测试的方法可以引发零个、一个或多个异常(例如,让它变得简单,只有一个)并且您想测试调用是否正常应该引发异常,如果你进入 catch 块,你将引发 Assert.fail();然后你想要在应该引发异常时测试用例,所以你调用 catch 块 Assert.assertTrue(true);说 "Yeah this is what I wanted"。从测试中,您可以在一种测试方法中看到它何时应该失败以及何时 运行 测试它是否真的像您想要的那样运行。
问题是:这是好事还是坏事?为什么?

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);
  }

}

使用 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
}

这使您的意图更加明确,并且您会看到如果没有抛出异常则测试失败。

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

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

断言一个常量true总是成功得无影无踪,所以你可以从你的代码中完全删除这一行。通过在必须抛出异常的测试代码行之后立即放置 Assert.fail(); 来捕获预期异常未被抛出的情况,并显示一条消息表明预期异常已抛出没有被抛出。

if you don't want to have zillion testing methods for one tested method, this could be option.

通常,"zillion testing methods" 是更好的选择。作为替代方案,您可以在测试中捕获 ExceptionRuntimeException,而不是捕获每个单独的异常。这在生产代码中是一个有问题的做法,但在必须确保不抛出异常的测试代码中绝对没问题。

但是,Assert.fail(); 并不是一种不常见的捷径,通常也是可以接受的。添加一条消息来描述失败背后的原因是个好主意,这样维护您的代码的人就不必通读您的测试以了解发生了什么。当您捕获异常时,它的消息是测试失败消息的一个很好的候选者。

第二种情况是不是少了什么? 我宁愿做下一个检查:

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

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

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

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

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

@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。忘记所有其他的;并学习使用那个。