我如何可以使用化成junit4习惯用法,测试,一些代码扔出一个例外吗?

而我可以肯定这样做:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

我记得,有一个注释或断言。xyz或 的东西 这远远小缺憾,远远更多的精神JUnit对这些各种各样的情况。

有帮助吗?

解决方案

JUnit 4支持:

@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {
    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);
}

参考: https://junit.org/junit4/faq.html#atests_7

其他提示

编辑现在JUnit5已经发布,最好的选择是使用 Assertions.assertThrows()(参见我的另一个答案)。

如果您尚未迁移到JUnit 5,但可以使用JUnit 4.7,则可以使用 ExpectedException 规则:

public class FooTest {
  @Rule
  public final ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    foo.doStuff();
  }
}

这比 @Test(expected = IndexOutOfBoundsException.class)要好得多,因为如果在 foo.doStuff()之前抛出 IndexOutOfBoundsException ,测试将会失败/代码>

有关详细信息,请参见本文

小心使用预期的异常,因为它只断言方法在测试中抛出了该异常,而不是特定的代码行

我倾向于使用它来测试参数验证,因为这些方法通常非常简单,但更复杂的测试可能更适合:

try {
    methodThatShouldThrow();
    fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}

判断。

如前所述,有许多方法可以处理JUnit中的异常。但是对于Java 8,还有另外一个:使用Lambda Expressions。使用Lambda Expressions,我们可以实现这样的语法:

@Test
public void verifiesTypeAndMessage() {
    assertThrown(new DummyService()::someMethod)
            .isInstanceOf(RuntimeException.class)
            .hasMessage("Runtime exception occurred")
            .hasMessageStartingWith("Runtime")
            .hasMessageEndingWith("occurred")
            .hasMessageContaining("exception")
            .hasNoCause();
}

assertThrown接受一个功能接口,其实例可以使用lambda表达式,方法引用或构造函数引用创建。 assertThrown接受该接口期望并准备好处理异常。

这是一种相对简单但功能强大的技术。

看看这篇描述这种技术的博客文章: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

源代码可以在这里找到: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

披露:我是博客和项目的作者。

在junit,有四种方式来测试例外。

  • 进化成junit4.x,使用可选择的"预期"属性的试验annonation

    @Test(expected = IndexOutOfBoundsException.class)
    public void testFooThrowsIndexOutOfBoundsException() {
        foo.doStuff();
    }
    
  • 进化成junit4.x,使用ExpectedException规则

    public class XxxTest {
        @Rule
        public ExpectedException thrown = ExpectedException.none();
    
        @Test
        public void testFooThrowsIndexOutOfBoundsException() {
            thrown.expect(IndexOutOfBoundsException.class)
            //you can test the exception message like
            thrown.expectMessage("expected messages");
            foo.doStuff();
        }
    }
    
  • 你也可以使用经典试图/抓住方式广泛使用的下junit3框架

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        try {
            foo.doStuff();
            fail("expected exception was not occured.");
        } catch(IndexOutOfBoundsException e) {
            //if execution reaches here, 
            //it indicates this exception was occured.
            //so we need not handle it.
        }
    }
    
  • 最后,对于junit5.x,你也可以使用如下assertThrows

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
        assertEquals("expected messages", exception.getMessage());
    }
    
  • 所以

    • 1的方法是使用时你只是想试验类型的例外
    • 其他三种方式是用来当你想测试的例外进一步的消息
    • 如果你使用junit3,然后第3个是优选的
    • 如果你喜欢junit5个,那么你应该喜欢的4个
  • 更多信息,你可以阅读 这份文件junit5用户指南 对于细节。

tl博士

  • 预JDK8:我会让老好的 try-catch 块。(不要忘记添加一个 fail() 断言之前 catch)

  • 后JDK8:使用AssertJ或定义lambda断言 特殊 行为。

无论Junit4或JUnit5.

在很长的故事

它是能够自己写的 做你自己 try-catch 块或使用JUnit工具(@Test(expected = ...)@Rule ExpectedException JUnit规则的功能)。

但是,这些方式不是那么优雅和不均匀 可读性,明智的 与其它工具。此外JUnit具有一些缺陷。

  1. try-catch 块你写的方框周围的测试行为,并编写的断言在赶块,这可能是好的,但许多发taht这种式样中断读流的一个测试。你也需要编写一个 Assert.fail 在结束 try 框否则的测试,可能会错过一侧的断言; PMD, 置的代声纳 会发现这样的问题。

  2. @Test(expected = ...) 特征是有趣的,因为你可以写下代码然后写这一试验被认为不易发生编码的错误。 部份的做法是缺乏某些领域。

    • 如果测试需要检查另外的事情上例外喜欢的原因或消息(良好的异常消息是非常重要的,具有精确的例外类型可能是不够的).
    • 也正如所期望的是放在周围的方法,取决于如何测试码是那么写的错误的测试的一部分代码,可以把异常,导致虚假的积极的测试我不确定 PMD, 置的代声纳 会给的提示这样的代码。

      @Test(expected = WantedException.class)
      public void call2_should_throw_a_WantedException__not_call1() {
          // init tested
          tested.call1(); // may throw a WantedException
      
          // call to be actually tested
          tested.call2(); // the call that is supposed to raise an exception
      }
      
  3. ExpectedException 规则也是一种尝试修复以前的警告,但它感到有点尴尬的使用,因为它使用的期望的风格, EasyMock 用户清楚地知道这种风格。这可能是便利一些,但如果你跟随 行为驱动的发展 (BDD)或 安排法》断言 (AAA)的原则 ExpectedException 规则不适合在那些写作风格。除了那可能遭受同样的问题,因为作为 @Test 方式,取决于你的地方的期望。

    @Rule ExpectedException thrown = ExpectedException.none()
    
    @Test
    public void call2_should_throw_a_WantedException__not_call1() {
        // expectations
        thrown.expect(WantedException.class);
        thrown.expectMessage("boom");
    
        // init tested
        tested.call1(); // may throw a WantedException
    
        // call to be actually tested
        tested.call2(); // the call that is supposed to raise an exception
    }
    

    甚至预期的例外之前放置的试验声明,它打破了你的读流动如果测试按照BDD或AAA。

    也看到这个 评论 问题在JUnit的作者 ExpectedException. JUnit4.13-beta-2 即使弃用这个机制:

    请求拉#1519:反对ExpectedException

    该方法的断言。assertThrows提供了一个更好的方式检验的例外情况。此外使用ExpectedException是容易出错的当使用与其它规则等TestWatcher因为订单的规则是重要的,在这种情况。

所以上述这些选择有他们所有的负载的事项,显然不能幸免于编码错误。

  1. 有一个项目,我开始意识到,在创建这个答案看起来很有希望,它的 赶异常.

    为描述项目的说,让一个编写一口流利的行代码醒目的例外和提供这种例外后面的断言。你可以使用的任何断言的图书馆喜欢 HamcrestAssertJ.

    一个快速的例子取自主页:

    // given: an empty list
    List myList = new ArrayList();
    
    // when: we try to get the first element of the list
    when(myList).get(1);
    
    // then: we expect an IndexOutOfBoundsException
    then(caughtException())
            .isInstanceOf(IndexOutOfBoundsException.class)
            .hasMessage("Index: 1, Size: 0") 
            .hasNoCause();
    

    正如你可以看到码真的很简单,你抓到的异常在一个特定的线路, then API是的别名,将使用AssertJ Api(类似于使用 assertThat(ex).hasNoCause()...). 在某一点项目依靠巨星-维护祖先的AssertJ. 编辑: 看来该项目正在酝酿一个Java8Lambda支持。

    目前,该图书馆有两个缺陷:

    • 当时写这篇文章值得注意的是说这个图书馆是基于Mockito1.x因为它创建了一个模拟测试对象背后的现场。作为Mockito是仍然没有更新 这个图书馆无法工作与最终的课程或最终的方法.甚至如果这是基于mockito2在目前的版本,这将需要宣布一个全球性模拟设备(inline-mock-maker),这东西可不是你想要的,因为这mockmaker具有不同的缺点,经常mockmaker.

    • 它需要又一个测试的依赖。

    这些问题不适用,一旦该图书馆将支持lambda,但是该功能将重复的AssertJ工具。

    把所有入帐户,如果你不想使用的捕异常的工具,我会让你老好的方式 try-catch 块,至少达到JDK7.和JAVA8个用户可能更喜欢使用AssertJ,因为它提供了可能更多只是主张的例外。

  2. 与JDK8,lambda进入现场测试,并且他们已被证明是一个有趣的方式来主张特殊的行为。AssertJ已经更新,以提供一个很好的流利API主张特殊的行为。

    和一个样本测试 AssertJ :

    @Test
    public void test_exception_approach_1() {
        ...
        assertThatExceptionOfType(IOException.class)
                .isThrownBy(() -> someBadIOOperation())
                .withMessage("boom!"); 
    }
    
    @Test
    public void test_exception_approach_2() {
        ...
        assertThatThrownBy(() -> someBadIOOperation())
                .isInstanceOf(Exception.class)
                .hasMessageContaining("boom");
    }
    
    @Test
    public void test_exception_approach_3() {
        ...
        // when
        Throwable thrown = catchThrowable(() -> someBadIOOperation());
    
        // then
        assertThat(thrown).isInstanceOf(Exception.class)
                          .hasMessageContaining("boom");
    }
    
  3. 有一个近乎完全重写JUnit5,断言已 改进 一位,它们可以证明有趣作为一个出来的盒子的方式伸张正确的例外。但真的断言API仍然是一个有点可怜的,没有什么外面 assertThrows.

    @Test
    @DisplayName("throws EmptyStackException when peeked")
    void throwsExceptionWhenPeeked() {
        Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
    
        Assertions.assertEquals("...", t.getMessage());
    }
    

    你注意到了 assertEquals 仍然是返回 void, ,因此不允许链的断言似AssertJ.

    如果你还记得姓名与冲突 MatcherAssert, 准备要满足同样的冲突与 Assertions.

我想得出结论,今天(2017-03-03) AssertJ's便于使用,发现API、快速发展的步伐和作为一个 事实上 测试的依赖是最好的解决方案与JDK8不论的测试框架(JUnit或不是),现有Jdk应,而不是依靠 try-catch 块甚至,如果他们觉得笨重。

此的答复已经拷贝 另一个问题 没有相同的可见性,我同一作者。

现在,JUnit5已经发布,最好的选择是使用 Assertions.assertThrows() (见 的 Junit5用户指南).

这里是一个例子,来验证一个异常,并使用 真相 做出的断言,在例外信息:

public class FooTest {
  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    IndexOutOfBoundsException e = assertThrows(
        IndexOutOfBoundsException.class, foo::doStuff);

    assertThat(e).hasMessageThat().contains("woops!");
  }
}

对优势的方法在其他的答案是:

  1. 建成JUnit
  2. 你会得到一个有用的例外信息,如果代码在lambda不会扔的一个例外,一个堆栈跟踪,如果这将引发一种不同的异常
  3. 简洁
  4. 允许你的测试的后续安排-行动-Assert
  5. 你可以精确地表明什么代码你是想扔异常
  6. 你不需要列出预期的例外 throws 条款
  7. 你可以使用的说法框架的选择做出的断言有关抓住了异常

一个类似的方法将加到 org.junit Assert 在JUnit4.13.

这个怎么样:捕获一个非常一般的异常,确保它使它脱离catch块,然后声明异常的类是你期望的那样。如果a)异常类型错误(例如,如果你有一个空指针)和b)没有抛出异常,那么这个断言将失败。

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}

BDD 风格的解决方案: JUnit4 + 抓住异常 + AssertJ

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    when(foo).doStuff();

    then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);

}

源代码

依赖关系

eu.codearte.catch-exception:catch-exception:1.3.3

使用 AssertJ 断言,可以与JUnit一起使用:

import static org.assertj.core.api.Assertions.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  Foo foo = new Foo();

  assertThatThrownBy(() -> foo.doStuff())
        .isInstanceOf(IndexOutOfBoundsException.class);
}

它比 @Test(expected = IndexOutOfBoundsException.class)更好,因为它可以保证测试中的预期行引发异常并让您检查有关异常的更多详细信息,例如消息,更容易:

assertThatThrownBy(() ->
       {
         throw new Exception("boom!");
       })
    .isInstanceOf(Exception.class)
    .hasMessageContaining("boom");

Maven / Gradle说明。

为了解决同样的问题,我设置了一个小项目: http://code.google.com/p/catch-exception/

使用这个小助手你会写

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

这比JUnit 4.7的ExpectedException规则简洁得多。 与skaffman提供的解决方案相比,您可以指定您期望异常的代码行。我希望这会有所帮助。

更新:JUnit5对异常测试有所改进: assertThrows

以下示例来自: Junit 5用户指南

 @Test
void exceptionTesting() {
    Throwable exception = assertThrows(IllegalArgumentException.class, () -> 
    {
        throw new IllegalArgumentException("a message");
    });
    assertEquals("a message", exception.getMessage());
}

使用JUnit 4的原始答案。

有几种方法可以测试抛出异常。我还在如何使用JUnit编写出色的单元测试中讨论了以下选项

设置 expected 参数 @Test(expected = FileNotFoundException.class)

@Test(expected = FileNotFoundException.class) 
public void testReadFile() { 
    myClass.readFile("test.txt");
}

使用尝试 catch

public void testReadFile() { 
    try {
        myClass.readFile("test.txt");
        fail("Expected a FileNotFoundException to be thrown");
    } catch (FileNotFoundException e) {
        assertThat(e.getMessage(), is("The file test.txt does not exist!"));
    }

}

使用 ExpectedException 规则进行测试。

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void testReadFile() throws FileNotFoundException {

    thrown.expect(FileNotFoundException.class);
    thrown.expectMessage(startsWith("The file test.txt"));
    myClass.readFile("test.txt");
}

您可以在 JUnit4 wiki for Exception testing 和 bad.robot - 期待异常JUnit规则

你也可以这样做:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
    try {
        foo.doStuff();
        assert false;
    } catch (IndexOutOfBoundsException e) {
        assert true;
    }
}

恕我直言,在JUnit中检查异常的最佳方法是try / catch / fail / assert模式:

// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
    sut.doThing();
    fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
                         // otherwise you may catch an exception for a dependency unexpectedly
    // a strong assertion on the message, 
    // in case the exception comes from anywhere an unexpected line of code,
    // especially important if your checking IllegalArgumentExceptions
    assertEquals("the message I get", e.getMessage()); 
}

assertTrue 对某些人来说可能有点强,所以 assertThat(e.getMessage(),containsString(" message"); 可能更好。

JUnit 5解决方案

@Test
void testFooThrowsIndexOutOfBoundsException() {    
  Throwable exception = expectThrows( IndexOutOfBoundsException.class, foo::doStuff );

  assertEquals( "some message", exception.getMessage() );
}

有关JUnit 5的更多信息,请访问 http://junit.org/junit5/文档/电流/用户引导/#写入测试 - 断言

我在这里尝试了很多方法,但它们要么很复杂,要么完全不符合我的要求。实际上,人们可以非常简单地编写辅助方法:

public class ExceptionAssertions {
    public static void assertException(BlastContainer blastContainer ) {
        boolean caughtException = false;
        try {
            blastContainer.test();
        } catch( Exception e ) {
            caughtException = true;
        }
        if( !caughtException ) {
            throw new AssertionFailedError("exception expected to be thrown, but was not");
        }
    }
    public static interface BlastContainer {
        public void test() throws Exception;
    }
}

像这样使用:

assertException(new BlastContainer() {
    @Override
    public void test() throws Exception {
        doSomethingThatShouldExceptHere();
    }
});

零依赖:不需要mockito,不需要powermock;并且在最后的课程中工作得很好。

Junit 4中最灵活,最优雅的答案我在 Mkyong博客。它具有使用 @Rule 注释的 try / catch 的灵活性。我喜欢这种方法,因为您可以阅读自定义异常的特定属性。

package com.mkyong;

import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;

public class Exception3Test {

    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testNameNotFoundException() throws NameNotFoundException {

        //test specific type of exception
        thrown.expect(NameNotFoundException.class);

        //test message
        thrown.expectMessage(is("Name is empty!"));

        //test detail
        thrown.expect(hasProperty("errCode"));  //make sure getters n setters are defined.
        thrown.expect(hasProperty("errCode", is(666)));

        CustomerService cust = new CustomerService();
        cust.findByName("");

    }

}

Java8解决方案

如果你想要一个解决方案:

  • 利用Java8lambda
  • 取决于任何JUnit魔法
  • 可以让你检查为多例外情况在一个单一的试验方法
  • 检查的例外时被抛通过一套具体的行你的测试方法,而不是任何未知的路线,在整个试验方法
  • 产生的实际例外的对象,被抛所以,你可以进一步审查它

这里是一个实用工具的功能,我写道:

public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
    try
    {
        runnable.run();
    }
    catch( Throwable throwable )
    {
        if( throwable instanceof AssertionError && throwable.getCause() != null )
            throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
        assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
        assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
        @SuppressWarnings( "unchecked" )
        T result = (T)throwable;
        return result;
    }
    assert false; //expected exception was not thrown.
    return null; //to keep the compiler happy.
}

(从我的博客)

使用如下:

@Test
public void testThrows()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            throw new RuntimeException( "fail!" );
        } );
    assert e.getMessage().equals( "fail!" );
}

JUnit内置了对此的支持,其中包含“预期”。属性

在我的情况下,我总是从db获取RuntimeException,但消息不同。并且需要分别处理异常。以下是我测试它的方法:

@Test
public void testThrowsExceptionWhenWrongSku() {

    // Given
    String articleSimpleSku = "999-999";
    int amountOfTransactions = 1;
    Exception exception = null;

    // When
    try {
        createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
    } catch (RuntimeException e) {
        exception = e;
    }

    // Then
    shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}

private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
    assertNotNull(e);
    assertTrue(e.getMessage().contains(message));
}

只需制作一个可以关闭和打开的匹配器,如下所示:

public class ExceptionMatcher extends BaseMatcher<Throwable> {
    private boolean active = true;
    private Class<? extends Throwable> throwable;

    public ExceptionMatcher(Class<? extends Throwable> throwable) {
        this.throwable = throwable;
    }

    public void on() {
        this.active = true;
    }

    public void off() {
        this.active = false;
    }

    @Override
    public boolean matches(Object object) {
        return active && throwable.isAssignableFrom(object.getClass());
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("not the covered exception type");
    }
}

使用它:

添加 public ExpectedException exception = ExpectedException.none(); , 然后:

ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();

在JUnit 4或更高版本中,您可以按如下方式测试例外

@Rule
public ExpectedException exceptions = ExpectedException.none();


这提供了许多可用于改进JUnit测试的功能。
如果您看到以下示例,我正在测试异常中的3件事。

  1. 抛出的异常类型
  2. 例外消息
  3. 异常原因
  4. 结果

    public class MyTest {
    
        @Rule
        public ExpectedException exceptions = ExpectedException.none();
    
        ClassUnderTest classUnderTest;
    
        @Before
        public void setUp() throws Exception {
            classUnderTest = new ClassUnderTest();
        }
    
        @Test
        public void testAppleisSweetAndRed() throws Exception {
    
            exceptions.expect(Exception.class);
            exceptions.expectMessage("this is the exception message");
            exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
    
            classUnderTest.methodUnderTest("param1", "param2");
        }
    
    }
    

我们可以在必须返回异常的方法之后使用断言失败:

try{
   methodThatThrowMyException();
   Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
   // Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
   assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
   // In case of verifying the error message
   MyException myException = (MyException) exception;
   assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}

另外为什么 NamShubWriter 所说的那样,确保:

  • 该ExpectedException实例 公共 (相关的问题)
  • 该ExpectedException 是不是 实例说,@前的方法。此 清楚地解释所有的错综复杂的JUnit的先后顺序执行。

这样做:

@Rule    
public ExpectedException expectedException;

@Before
public void setup()
{
    expectedException = ExpectedException.none();
}

最后, 博客清楚地说明了如何断言,一定会引发异常。

我建议使用库 assertj-core 来处理junit测试中的异常

在java 8中,像这样:

//given

//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));

//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);

使用Java8的Junit4解决方案是使用此功能:

public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
    try {
        funky.call();
    } catch (Throwable e) {
        if (expectedException.isInstance(e)) {
            return e;
        }
        throw new AssertionError(
                String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
    }
    throw new AssertionError(
            String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}

然后用法:

    assertThrows(ValidationException.class,
            () -> finalObject.checkSomething(null));

请注意,唯一的限制是在lambda表达式中使用 final 对象引用。 此解决方案允许继续测试断言,而不是期望在方法级别使用 @Test(expected = IndexOutOfBoundsException.class)解决方案可以使用。

例如,您想为下面提到的代码片段

编写Junit
public int divideByZeroDemo(int a,int b){

    return a/b;
}

public void exceptionWithMessage(String [] arr){

    throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}

上面的代码是为了测试可能发生的一些未知异常,下面的代码是用自定义消息声明一些异常。

 @Rule
public ExpectedException exception=ExpectedException.none();

private Demo demo;
@Before
public void setup(){

    demo=new Demo();
}
@Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {

    demo.divideByZeroDemo(5, 0);

}

@Test
public void testExceptionWithMessage(){


    exception.expectMessage("Array is out of bound");
    exception.expect(ArrayIndexOutOfBoundsException.class);
    demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}

Java8您可以创建一个方法把一个代码检查和预期的例外作为参数:

private void expectException(Runnable r, Class<?> clazz) { 
    try {
      r.run();
      fail("Expected: " + clazz.getSimpleName() + " but not thrown");
    } catch (Exception e) {
      if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
    }
  }

然后在你的测试:

expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);

福利:

  • 不依靠任何库
  • 局部检查-更精确,并允许有多个主张这样的内的一个测试,如果需要的
  • 容易使用

我使用Java 8 lambdas的解决方案:

public static <T extends Throwable> T assertThrows(Class<T> expected, ThrowingRunnable action) throws Throwable {
    try {
        action.run();
        Assert.fail("Did not throw expected " + expected.getSimpleName());
        return null; // never actually
    } catch (Throwable actual) {
        if (!expected.isAssignableFrom(actual.getClass())) { // runtime '!(actual instanceof expected)'
            System.err.println("Threw " + actual.getClass().getSimpleName() 
                               + ", which is not a subtype of expected " 
                               + expected.getSimpleName());
            throw actual; // throw the unexpected Throwable for maximum transparency
        } else {
            return (T) actual; // return the expected Throwable for further examination
        }
    }
}

您必须定义一个FunctionalInterface,因为 Runnable 不会声明所需的 throws

@FunctionalInterface
public interface ThrowingRunnable {
    void run() throws Throwable;
}

该方法可以如下使用:

class CustomException extends Exception {
    public final String message;
    public CustomException(final String message) { this.message = message;}
}
CustomException e = assertThrows(CustomException.class, () -> {
    throw new CustomException("Lorem Ipsum");
});
assertEquals("Lorem Ipsum", e.message);

编写测试用例有两种方法

  1. 使用方法抛出的异常来注释测试。像这样的 @Test(expected = IndexOutOfBoundsException.class)
  2. 您可以使用try catch块在测试类中捕获异常,并对从测试类中的方法抛出的消息进行断言。

    try{
    }
    catch(exception to be thrown from method e)
    {
         assertEquals("message", e.getmessage());
    }
    
  3. 我希望这可以回答您的问题 快乐学习......

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top