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

时间:2011-09-01 15:32:23

标签: java testing junit

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

@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无论如何都会抛出异常。有没有更好的方法来处理这些预期的异常,可能是一种默认失败的方式 - 迫使我努力处理这些情况?

5 个答案:

答案 0 :(得分:3)

我同意你提出的风格不太好。问题是它没有检查抛出异常的方法中的 where ,因此可能会出现漏报。

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

public void testWorldMapIntInt() {
    try {
        WorldMap w = new WorldMap(-1, -1);
        Assert.fail("should have thrown IndexOutOfBoundsException");
    }
    catch (IndexOutOfBoundsException e) {}
}

答案 1 :(得分:2)

  1. WorldMap的预期行为是在传递(-1,-1)时抛出异常
  2. 最初它没有这样做,因此您的测试将失败,因为它没有看到预期的异常。
  3. 您正确实现了WorldMap的代码,包括在传入(-1,-1)时抛出异常。
  4. 你重新运行测试,它通过了。
  5. 对我来说听起来像TDD一样好!

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

同意接受的答案,try-fail-catch成语虽然丑陋且混乱,但比@Test(expcted=...)好得多,因为它可能会报告误报。

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

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

请参阅blog postsource