java - Spring 的 @Retryable 在运行 JUnit 测试时不起作用

标签 java spring maven junit spring-retry

我有这个测试:

@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";
 }
}

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

public interface myServiceInterface {

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

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

}

但是,我在运行测试时抛出了运行时异常,这让我相信它没有重试。我做错了吗?

最佳答案

这是因为您没有使用 SpringJUnitClassRunner .

Mockito 和您自己的类没有考虑 @Retryable 注释。所以你依赖于 Spring 的实现来做到这一点。但是您的测试不会激活 Spring。

这是来自 SpringJUnit4ClassRunner JavaDoc:

SpringJUnit4ClassRunner is a custom extension of JUnit's BlockJUnit4ClassRunner which provides functionality of the Spring TestContext Framework to standard JUnit tests by means of the TestContextManager and associated support classes and annotations. To use this class, simply annotate a JUnit 4 based test class with @RunWith(SpringJUnit4ClassRunner.class) or @RunWith(SpringRunner.class).

您应该至少将您的测试类重构为:

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

我在那里做什么?

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

还有其他陷阱吗?

  • 是的,您正在使用 Mockito 来模拟异常。如果你想像这样用 Spring 测试这种行为,你应该看看 Springockito Annotations .
  • 但请注意:Springockito 将完全替换 spring bean,这会迫使您代理可重试的调用。您需要这样的结构:test -> retryableService -> exceptionThrowingBean。然后你可以使用 Springockito 或任何你喜欢的东西,例如ReflectionTestUtils 以您喜欢的行为配置 exceptionThrowingBean
  • 您应该在测试中引用服务的接口(interface)类型:MyServiceInterface
  • 最后但并非最不重要的一点。有一个几乎所有 Java 开发人员都遵循的命名约定:类名每个内部单词的第一个字母大写

希望对您有所帮助。

关于java - Spring 的 @Retryable 在运行 JUnit 测试时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39478665/

相关文章:

java - 使用 Spring Rest 将 ID 转换为类类型

java - Spring 刷新 bean 有间隔

java - 将主项目jar添加到项目根文件夹中

java - 将 tiff 转换为缓冲图像 (Java)

java - HttpServletResponse将多个图像写入OutputStream(在同一查询中)

java - jvnet maven-jaxb2-plugin 版本 0.13.0 的 Eclipse 错误消息

java - 如何防止每次在Docker Maven插件中运行Docker镜像?

java - 批量更新缓存问题? hibernate/集成测试/内存数据库/

Java List对象继承问题

java - 为什么 sleep 可以解决 "No Transaction is currently active"JPA