【问题标题】:Java/Mockito - A unit test for the thread to sleep exponentially before retryJava/Mockito - 线程在重试之前以指数方式休眠的单元测试
【发布时间】:2019-02-06 20:56:58
【问题描述】:

我正在尝试创建一个单元测试类来测试我创建的类。此类尝试发送消息,如果发送失败,它将以指数方式等待(1s、2s、4s、8s 等),然后重试发送消息。我想测试这种指数等待行为是否正常工作。但我是单元测试的新手,不太确定如何使用 JUnit 和 Mockito 进行测试。任何帮助将不胜感激!

@Slf4j
@Setter
@RequiredArgsConstructor
@AllArgsConstructor(access = AccessLevel.PACKAGE)
public class RetriableProcessorExponentialDecorator implements   
        AbsMessageProcessorDecorator {
    private final AbsMessageProcessor messageProcessor;
    @Autowired
    private AbsMessageActiveMQConfiguration configuration;

    @Override
    public void onMessage(AbsMessage message) throws Exception {
        int executionCounter = 0;
        long delay = 1000;
        final int maxRetries = this.configuration.getExceptionRetry() + 1;
        do {
            executionCounter++;
            try {
                this.messageProcessor.onMessage(message);
            } catch (RetriableException e) {
                log.info("Failed to process message. Retry #{}", executionCounter);
                delay = (long) (delay * (Math.pow(this.configuration.getMultiplier(), executionCounter)));
                Thread.sleep(delay);
            } catch (Exception e) {
                // We don't retry on this, only RetriableException.
                throw e;
            }
        } while (executionCounter < maxRetries && delay < Long.MAX_VALUE);
    }
}

P.S 根据@Andy Turner 的建议,我在我的RetriableProcessorExponentialDecorator 类中添加了一行private final DefaultSleeper defaultSleeper;,然后将Thread.sleep(delay) 替换为defaultSleeper.sleep(delay)

然后在我的单元测试类中,我通过 @Mock private DefaultSleeper sleeper; 模拟 DefaultSleeper 并通过 RetriableProcessorExponentialDecorator 的构造函数传递模拟对象,如下所示:

@Before
public void setUp() {
    this.decorator = new   
    RetriableProcessorExponentialDecorator(sleeper, processor,   
    configuration);
}

我走对了吗?

【问题讨论】:

  • 我不会测试等待,我会测试它根据尝试次数计算等待时间的方法返回正确结果

标签: java spring unit-testing junit mockito


【解决方案1】:

创建一个类似这样的接口:

interface Sleeper {
  void sleep(long delay) throws InterruptedException;
}

然后你可以创建一个实现:

class DefaultSleeper implements Sleeper {
  @Override public void sleep(long delay) throws InterruptedException { 
    Thread.sleep(delay);
  }
}

并模拟它:Sleeper sleeper = mock(Sleeper.class);

现在您可以将其实例注入您的RetriableProcessorExponentialDecorator,并在您的测试中测试与模拟的交互。

【讨论】:

  • 是否可以同时展示注入实例和测试交互部分?我不确定我是否完全理解这些部分
  • 以constructor为例。
  • 注入 this 的实例是不是应该替换当前的 Thread.sleep(delay); (这是我当前代码中的流行语)与 instanceName.sleep(delay)?
猜你喜欢
  • 2011-06-19
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多