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

如何用JUnit/Mockito测试模拟重试时只抛出一次异常?

叶举
2023-03-14

我放了一个简单的重试,因为操作很少会失败。下面是简化的代码。方法< code>putObject可能会意外引发异常,在这种情况下,重试应该允许再次调用此方法。有可能为此编写一个JUnit测试吗?我知道使用Mockito library我们可以强制抛出一个调用方法的异常,但是如何强制这个异常只抛出一次呢?

public class RetryExample {
Bucket bucket = new Bucket();
static int INTERNAL_EXCEPTION_CODE = 100;
class AException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    int statusCode;
    public int getStatusCode() {
        return statusCode;
    }
}

class Bucket {
    public void putObject(String fileName, byte[] data) throws AException {
        System.out.println("PutObject=" + fileName + " data=" + data);
    }
}

public void process(String fileName, byte[] data) throws AException {
    try {
        retryOperation((f, d) -> bucket.putObject(f, d), fileName, data);
    } catch (Exception ex) {
        throw new AException("Failed to write data", ex);
    }
}

private <T, U> void retryOperation(BiConsumer<T, U> biConsumer, T t, U u) {
    int retries = 0;
    boolean retry = false;
    AException lastServiceException = null;
    do {
        try {
            biConsumer.accept(t, u);
        } catch (AException e) {
            lastServiceException = e;
            int statusCode = e.getStatusCode();
            if (statusCode == INTERNAL_EXCEPTION_CODE) {
                throw e;
            } else {
                break;
            }
        }
        retries++;
        if (retries >= 3) {
            retry = false;
        }
    } while (retry);
    if (lastServiceException != null) {
        throw lastServiceException;
    }
}

测试类:

public class RetryExampleTest {
...
@Test
public void test() {
    RetryExample retryExample = new RetryExample();
    String fileName = "TestFile";
    byte[] data = simulatedPayload(10000);
    try {
        retryExample.process(fileName, data);
    } catch (Exception e) {
        fail("Exception thrown=" + e);
    }
}

共有2个答案

宗政子辰
2023-03-14

我认为可以使用一个全局数据对象来存储抛出异常的次数,所以在Mockito库中调用Exception方法时只是取了全局数据对象来记录次数。这很简单。一切都由你控制。

公羊招
2023-03-14

根据Mockito文档,您可以为连续的方法调用设置不同的行为。

when(mock.someMethod("some arg"))
    .thenThrow(new RuntimeException())
    .thenReturn("foo");

在void方法的情况下,您可以做类似的事情(Mockito文档)

doThrow(new RuntimeException())
    .doNothing()
    .when(mock).doSomething();
 类似资料:
  • 我应该如何测试异常?我可以mock connector并且我可以赋予它抛出异常的行为,但是我不明白下一步该怎么做。

  • 问题内容: 我有一个Java命令行程序。我想创建JUnit测试用例以进行模拟。因为当我的程序运行时,它将进入while循环并等待用户输入。如何在JUnit中模拟呢? 问题答案: 从技术上讲,可以进行切换,但是总的来说,不直接在代码中调用它,而是添加一层间接层,这样输入源就可以从应用程序的某个位置进行控制,这样会更健壮。确切地讲,这是实现的详细信息-依赖项注入的建议很好,但是你不一定需要引入第三方框

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

  • 假设我有以下功能: 根据Jest文档,我应该能够使用以下代码测试函数是否引发异常: 但是,我得到了以下错误。 有人能告诉我我做错了什么吗? 谢谢!

  • 问题内容: 我在junit测试中使用了模仿。如何使异常发生,然后断言其具有(通用伪代码) 问题答案: __仅 Mockito 并不是处理异常的最佳解决方案, 请将Mockito 与 Catch-Exception结合使用 Mockito + 捕获异常 + AssertJ 样例代码 Mockito + Catch-Exception + Assertj完整样本 依存关系 eu.codearte.ca

  • 我正试图为一个方法编写一个测试用例,该方法基于特定的逻辑抛出异常。然而,测试用例失败了,因为预期的异常和获得的异常是不同的。 我如何解决这个问题?