本文介绍了运行JUnit Test时Spring的@Retryable无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个测试:

@RunWith(MockitoJUnitRunner.class)
public class myServiceTest {

@InjectMocks
myService subject;

private myService spy;

@Before
public void before() {
    spy = spy(subject);
}

@Test
public void testing() {

    when(spy.print2()).thenThrow(new RuntimeException()).thenThrow(new RuntimeException()).thenReturn("completed");
    spy.print1();
    verify(spy, times(3)).print2();
}

然后我有

@Service("myService")
public class myService extends myAbstractServiceClass {


public String print1() {
    String temp = "";
    temp = print2();
    return temp;
}

 @Retryable
 public String print2() {
     return "completed";
 }
}

然后我有这个接口(我的abstractService实现了):

then I have this interface(which my abstractService implements):

public interface myServiceInterface {

    @Retryable(maxAttempts = 3)
    String print1() throws RuntimeException;

    @Retryable(maxAttempts = 3)
    String print2() throws RuntimeException;

}

但是,当我运行测试时,我抛出了运行时异常,这使我相信它不会重试.我做错了吗?

but, I get a runtimeexception thrown when I run the test, leading me to believe it is not retrying. Am I doing this wrong?

推荐答案

这是因为您没有使用 SpringJUnitClassRunner .

This is because you are not using the SpringJUnitClassRunner.

Mockito和您自己的类未考虑@Retryable注释.因此,您需要依靠Spring的实现.但是您的测试不会激活Spring.

Mockito and your own classes are not taking the @Retryable annotation in account. So you rely on the implementation of Spring to do so. But your test does not activate Spring.

这来自SpringJUnit4ClassRunner JavaDoc:

This is from the SpringJUnit4ClassRunner JavaDoc:

您应该至少将测试类重组为以下内容:

You should restructure your test class at least to something like:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=MyConfig.class)
public class MyServiceTest {
    @Configuration
    @EnableRetry
    @Import(myService.class)
    public static class MyConfig {}
...

我在那里做什么?

  1. 激活Spring JUnit钩子
  2. 指定Spring上下文配置类
  3. 定义spring配置并将您的服务作为Bean导入
  4. 启用可重试注释

还有其他陷阱吗?

  • 是的,您正在使用Mockito模拟异常.如果您想像这样用Spring测试这种行为,您应该看看 Springockito注释.
  • 但是请注意:Springockito将完全替换spring bean,这将迫使您代理可重试的调用.您需要这样的结构:test -> retryableService -> exceptionThrowingBean.然后,您可以使用Springockito或任何您喜欢的东西,例如ReflectionTestUtils使用您喜欢的行为配置exceptionThrowingBean.
  • 您应该在测试中引用服务的接口类型:MyServiceInterface
  • 最后但并非最不重要的一点.几乎所有Java开发人员都遵循一个命名约定:类名带有first letter of each internal word capitalized
  • Yes, you are using Mockito to simulate an exception. If you want to test this behaviour with Spring like this, you should have a look at Springockito Annotations.
  • But be aware of that: Springockito you will replace the spring bean completely which forces you to proxy the call of your retryable. You need a structure like: test -> retryableService -> exceptionThrowingBean. Then you can use Springockito or what ever you like e.g. ReflectionTestUtils to configure the exceptionThrowingBean with the behaviour you like.
  • You should reference the interface type of your service in your test: MyServiceInterface
  • And last but not least. There is a naming convention nearly all Java developers follow: class names have first letter of each internal word capitalized

希望有帮助.

这篇关于运行JUnit Test时Spring的@Retryable无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-06 04:14