如何模拟在JUNIT / Mockito测试重试时只抛出一次异常? [英] How to simulate throwing an exception only once in retry with JUNIT/Mockito test?

查看:158
本文介绍了如何模拟在JUNIT / Mockito测试重试时只抛出一次异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I put a simple retry because the operation can rarely fail. The simplified code is below. The method putObject can accidentally throw an exception, in this case the retry should allow to invoke this method again. Is it possible to write a JUnit test for this? I know that with Mockito library we can force to throw an Exception invoking a method but how to force this exception to be thrown only once?

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


推荐答案

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

According to the Mockito documentation you can set different behavior for consecutive method calls.

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

如果是void方法,你可以做类似的事情( Mockito文档

In case of a void method you can do something similar (Mockito documentation)

doThrow(new RuntimeException())
    .doNothing()
    .when(mock).doSomething();

这篇关于如何模拟在JUNIT / Mockito测试重试时只抛出一次异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆