在JUnit测试用例中,“fail”的实际用途是什么?

woobm2wo  于 2023-06-23  发布在  其他
关注(0)|答案(9)|浏览(161)

在JUnit测试用例中,“fail”的实际用途是什么?

kiayqfof

kiayqfof1#

我发现它很有用的一些案例:

  • 标记一个未完成的测试,使其失败并警告您,直到您可以完成它
  • 确保抛出异常:
try{
  // do stuff...
  fail("Exception not thrown");
}catch(Exception e){
  assertTrue(e.hasSomeFlag());
}

注意事项:
从JUnit4开始,有一种更优雅的方法来测试异常是否被抛出:使用注解@Test(expected=IndexOutOfBoundsException.class)
但是,如果您还想检查异常,那么这将不起作用,您仍然需要fail()

nhn9ugyo

nhn9ugyo2#

假设您正在编写一个负流的测试用例,其中被测试的代码应该引发一个异常。

try{
   bizMethod(badData);
   fail(); // FAIL when no exception is thrown
} catch (BizException e) {
   assert(e.errorCode == THE_ERROR_CODE_U_R_LOOKING_FOR)
}
pb3s4cty

pb3s4cty3#

我认为通常的用例是在否定测试中没有抛出异常时调用它。
类似于下面的伪代码:

test_addNilThrowsNullPointerException()
{
    try {
        foo.add(NIL);                      // we expect a NullPointerException here
        fail("No NullPointerException");   // cause the test to fail if we reach this            
     } catch (NullNullPointerException e) {
        // OK got the expected exception
    }
}
pkmbmrz7

pkmbmrz74#

我已经在@Before方法出错的情况下使用了它。

public Object obj;

@Before
public void setUp() {
    // Do some set up
    obj = new Object();
}

@Test
public void testObjectManipulation() {
    if(obj == null) {
        fail("obj should not be null");
     }

    // Do some other valuable testing
}
pqwbnv8z

pqwbnv8z5#

这就是我使用失败方法的方式。
您的测试用例可能以三种状态结束
1.通过:被测函数成功执行并按预期返回数据
1.未通过:被测函数成功执行,但返回的数据与预期的不一致

  1. Failed:函数没有成功执行,这不是
    预期的(与预期发生异常的负测试用例不同)。
    如果您使用eclipse,则有三种状态分别由绿色,蓝色和红色标记表示。
    我在第三种情况下使用fail操作。
    例如:public Integer add(integer a,Integer b){return new Integer(a. intValue()+b. intValue())}
    1.通过病例:a = new Integer(1),b = new Integer(2),函数返回3
    1.未通过病例:a = new Integer(1),b = new Integer(2),函数返回的值不是3
    1.失败案例:a = null,b = null,函数抛出NullPointerException
vaqhlq81

vaqhlq816#

例如,我使用fail()来表示尚未完成的测试(它发生了);否则,它们将显示为成功的。
这可能是因为我不知道NUnit中存在某种不完整的()功能。

pn9klfpd

pn9klfpd7#

在并发和/或异步设置中,您可能需要验证某些方法(例如委托、事件侦听器、响应处理程序,等等)都不会被调用。除了模拟框架之外,您可以在这些方法中调用fail()来使测试失败。超时过期是此类场景中的另一个自然故障条件。
例如:

final CountDownLatch latch = new CountDownLatch(1);

service.asyncCall(someParameter, new ResponseHandler<SomeType>() {
    @Override
    public void onSuccess(SomeType result) {
        assertNotNull(result);
        // Further test assertions on the result
        latch.countDown();
    }

    @Override
    public void onError(Exception e) {
        fail(exception.getMessage());
        latch.countDown();
    }
});

if ( !latch.await(5, TimeUnit.SECONDS) ) {
    fail("No response after 5s");
}
deikduxw

deikduxw8#

最重要的用例可能是异常检查。
虽然junit4包含了用于检查是否发生异常的预期元素,但它似乎不是较新的junit5的一部分。与expected相比,使用fail()的另一个优点是可以将其与finally结合使用,从而允许测试用例清理。

dao.insert(obj);
try {
  dao.insert(obj);
  fail("No DuplicateKeyException thrown.");
} catch (DuplicateKeyException e) {
  assertEquals("Error code doesn't match", 123, e.getErrorCode());
} finally {
  //cleanup
  dao.delete(obj);
}

正如另一条评论所指出的。让一个测试失败,直到你完成它的实现,这听起来也是合理的。

brgchamk

brgchamk9#

下面是一个简短的Junit 5示例,说明了单元测试失败和错误之间的区别。(注意,JUnit 5有一个assertThrows(…)方法,因此很少需要使用fail(…)来指示不存在异常。
假设我有一个方法deleteFileTree(Path fileTreeRoot)来删除一个目录,即使其中有文件。我的方法是有效的,除了我第一次写它时假设有一个目录要删除。在这个领域,我遇到了一个目录不存在的情况,它抛出了一个NoSuchFileException。我希望这个方法是幂等的(如果我们试图删除一个丢失的目录,或者如果我们删除目录两次,这不是问题),所以我修复了这个问题。集成测试如下所示:

@Test
void verifyDeleteFileTreeThrowsNoExceptionIfPathDoesNotExist(@TempDir Path tempDir) throws IOException {
  try {
    final Path missingDir = tempDir.resolve("missing");
    assertThat(Files.deleteFileTree(missingDir), is(missingDir));
  } catch(final NoSuchFileException noSuchFileException) {
    fail("Should not throw exception if path is already missing.", noSuchFileException);
  }
}

在本例中,测试是为了确保它不会抛出NoSuchFileException;如果是,则测试 * 失败 *。但是如果抛出了其他的异常,测试就会有一个 error,因为问题是意料之外的,并且与我正在测试的内容无关。测试没有正常工作。
如果我没有检查NoSuchFileException并使用fail(…),则测试将指示错误条件。这在语义上是不正确的,因为测试工作正常,没有错误--确切地说,我测试的方法没有通过测试。

相关问题