检查JUnit中的exception的最佳做法是什么?

我正在努力编写测试用例。 根据我的阅读,我的测试应该从一开始就失败,我应该努力让测试通过。 但是,我发现自己编写测试检查边界以及它们应该导致的exception:

@Test(expected=NegativeArraySizeException.class) public void testWorldMapIntInt() { WorldMap w = new WorldMap(-1, -1); } @Test(expected=IndexOutOfBoundsException.class) public void testGetnIntnInt() { WorldMap w = new WorldMap(10,10); Object o = w.get(-1, -1); } 

但是,此测试默认情况下会通过,因为Java无论如何都会抛出exception。 有没有更好的方法来处理这些预期的exception,可能是默认情况下失败的方式 – 迫使我努力处理这些情况?

我同意你提出的风格不太好。 问题是它没有检查方法中抛出exception的位置,因此可能会出现错误否定。

我们通常会为这样的exception编写测试:

 public void testWorldMapIntInt() { try { WorldMap w = new WorldMap(-1, -1); Assert.fail("should have thrown IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException e) {} } 
  1. WorldMap的预期行为是在传入(-1,-1)时抛出exception
  2. 最初它不会这样做,因此您的测试将失败,因为它没有看到预期的exception。
  3. 您正确实现了WorldMap的代码,包括在传入(-1,-1)时抛出exception。
  4. 你重新运行测试,它通过了。

对我来说听起来好TDD!

这似乎是一个公平的考试。 WorldMap不是标准的Java类。 大概是你自己的class级。 因此,如果您尚未编写某些代码,则测试不会通过。 此测试将强制您从类中抛出(或传播)适当的exception。 这听起来对我来说是一个很好的测试,你应该实现这个行为之前一下

我个人在WorldMap构造函数中查找类似的错误并抛出IllegalArgumentException,这样您就可以提供更好的错误消息,例如传入的值是什么以及预期的范围是什么。

至于默认情况下测试失败,我想不出一个合理的方法,如果你要让它真正做某事(如果你先编写测试然后它应该失败,因为构造函数将没有任何代码)。

同意接受的答案, try-fail-catch习惯,虽然丑陋和混乱的测试,比@Test(expcted=...)要好得多,因为它可能会报告误报。

前段时间我实现了非常简单的JUnit规则,以安全和可读的方式处理exception测试:

 public class DefaultFooServiceTest { @UnderTest private FooService fooService = new DefaultFooService(); @Rule public ExceptionAssert exception = new ExceptionAssert(); @Test public void shouldThrowNpeWhenNullName() throws Exception { //given String name = null; //when fooService.echo(name); //then exception.expect(NullPointerException.class); } @Test public void shouldThrowIllegalArgumentWhenNameJohn() throws Exception { //given String name = "John"; //when fooService.echo(name); //then exception.expect(IllegalArgumentException.class) .expectMessage("Name: 'John' is not allowed"); } } 

查看博客文章和来源 。