当前位置: 首页 > 知识库问答 >
问题:

JUnit/Mockito:在新线程中抛出异常

戚哲
2023-03-14

我正在为以下Java代码编写单元测试:

try {
    new Thread(() -> myService.myMethod()).start();
    return new MyResponse("Done");
} catch (Exception exception) {
    throw new MyException("Internal Error", exception);
}

我试图模拟myService抛出错误的过程。myMethod(),以便在上面代码的catch块中提取它,并抛出MyException实例。

在我的JUnit测试中(使用org.springframework.test.context.junit4. SpringJUnit4ClassRunner和Mockito),我嘲笑了MyService并将其作为Spring bean注入单元测试:

MyService myService = Mockito.mock(MyService.class);

然后,我尝试这样做来模拟服务引发异常:

IllegalArgumentException myException = new IllegalArgumentException();
Mockito.doThrow(myException).when(myService).myMethod();

... 但我正在测试的方法的catch块中从未发现异常。

这可能与代码正在使用另一个线程调用myService有关。myMethod()。

是否有任何方法可以获取myService引发的异常。要正确捕获myMethod()?

提前感谢任何帮助。

共有2个答案

徐昕
2023-03-14

您的代码执行顺序如何?首先您需要设置您的mock,然后运行它。

MyService myService = Mockito.mock(MyService.class);
Mockito.when(myService.myMethod()).doThrow(myexception.class); // try in this order


try {
    new Thread(() -> myService.myMethod()).start();
    return new MyResponse("Done");
} catch (Exception exception) {
    throw new MyException("Internal Error", exception);
}

顺便说一下,如果您使用的是java 8或更高版本,您可能希望使用CompletableFuture包。也就是说,CompletableFuture。SupplySync(()-

谯皓君
2023-03-14

“外部”线程可以捕获另一个线程中的异常是没有意义的。如果在代码中添加上下文,例如

Thread th = new Thread(() -> { Thread.sleep(10000); throw new RuntimeException(); });
try { th.start(); } catch (Exception e) {
    System.out.println("uh-oh");
}
for (int i = 0; i < 1000; i++){
    System.out.println("running " + i);
    Thread.sleep(1000);
}

线程已启动,并将在10秒后引发异常。然而,开始线程已转到每秒计数。如果启动线程的异常将被捕获,您是否希望主线程返回到捕获异常的位置?是否应中断计数,然后继续?不继续?

您所能做的最好的事情可能是指定一个错误处理程序(就像Roger在评论中提到的那样),但您必须以实际的间隔从主线程查询其状态,因为它将在并发启动的线程中运行。

考虑到t=new Thread();t.start();不建议再使用,最简单的方法是使用CompletableFutureIMO:

CompletableFuture<Void> future = 
    CompletableFuture.runAsync(() -> myService.myMethod());

现在,您可以稍后查询发生了什么:

if (future.isDone()) // task has finished in any way

if (future.isDone() && future.isCompletedExceptionally()) // task was finished because an exception was thrown
 类似资料:
  • 我正在使用ModelMapper进行NPE 目录服务测试 目录服务 目录映射器 目录库 按预期返回CatalogEntity对象,问题出现在执行返回null之后。

  • 问题内容: 我有一个关于Java中重新引发异常的非常简单的问题。 这是代码片段: 为什么我们需要在第一个版本中重新抛出,而第二个版本看起来更优雅?可能有什么好处,并且优先选择哪个版本? 问题答案: 你是对的。第二版更好。而且,第一个版本没有任何意义。除了异常的堆栈跟踪为“错误”之外,它的功能相同。 有“重新抛出”异常的原因如下: 如果您之前有事要做。 如果捕获一种类型的异常并抛出另一种类型的异常:

  • 问题内容: 我正在尝试嘲笑课堂。当我运行以下代码时,Mockito会引发异常: 堆栈跟踪是无限重复的以下几行: 我在这里做错了什么? 问题答案: PS!您还可以模拟对getSecurityManager()方法的静态方法调用。 模拟静态方法请参见maunal,网址为http://code.google.com/p/powermock/wiki/MockitoUsage 在类级别添加@Prepare

  • 我目前有以下示例代码,我试图将OutputStream转换为InputStream,这是我从http://blog.ostermiller.org/convert-java-outputStream-InputStream中的获得的想法 但这里我的问题是,save方法可能会抛出IOException,我希望捕获它,并将其作为getInputStream方法的一部分重新抛出。 我读过如何从线程捕捉异

  • 我在测试跟随功能。 下面是测试代码。 我定义了以下变量。 问题是不会引发异常。所以测试一直失败。 请告诉我我缺少的东西。

  • 我应该如何测试异常?我可以mock connector并且我可以赋予它抛出异常的行为,但是我不明白下一步该怎么做。