You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带重试逻辑方法的单元测试:验证异常触发重试

Troubleshooting Your Retry Logic Unit Test

Hey there, let's break down why your test isn't validating the retry behavior correctly, and fix it step by step.

First, the core issues with your current code:

  • When you create a mock of StoreFiles with Mockito.mock(StoreFiles.class), calling storeFiles() on that mock doesn't execute the real method logic (including your custom retry annotation). Mockito replaces the real implementation with a no-op, so there's no retry logic to trigger—hence why your verify only sees one call.
  • When using the @Tested instance, you're probably not properly mocking your dependencies to throw the CustomException that triggers the retry, or the retry annotation's aspect/proxy isn't active for the test instance.

Here's the fixed test (using JMockit, since you're already using its annotations):

public class FileTest {
    String first;
    String second;
    Instant third;
    int fourth;

    @Tested
    StoreFiles storeFiles;

    @Injectable
    FileSystemFactory fileSystemFactory;

    @Injectable
    OracleConnection conn;

    @BeforeClass
    public void init() {
        first = "test";
        second = "testRoot";
        third = Instant.now();
        fourth = 1;
    }

    @Test
    public void testRetryOnCustomException() throws CustomException {
        // Mock the dependency method that your storeFiles() calls to throw CustomException
        // We specify it should throw twice (once for the initial call, once for the retry)
        new Expectations() {{
            // Replace "someMethodThatThrowsException()" with the actual method in FileSystemFactory
            // that triggers the CustomException in your storeFiles logic
            fileSystemFactory.someMethodThatThrowsException();
            result = new CustomException("Test trigger exception");
            times = 2;
        }};

        // Call the REAL method on your tested StoreFiles instance
        storeFiles.storeFiles(conn, first, second, third, fourth);

        // Verify the dependency method was called twice—proof the retry ran
        new Verifications() {{
            fileSystemFactory.someMethodThatThrowsException();
            times = 2;
        }};
    }
}

If you prefer sticking with Mockito instead:

public class FileTest {
    String first;
    String second;
    Instant third;
    int fourth;

    @InjectMocks
    StoreFiles storeFiles;

    @Mock
    FileSystemFactory fileSystemFactory;

    @Mock
    OracleConnection conn;

    @Before
    public void initMocks() {
        MockitoAnnotations.openMocks(this);
    }

    @BeforeClass
    public void init() {
        first = "test";
        second = "testRoot";
        third = Instant.now();
        fourth = 1;
    }

    @Test
    public void testRetryOnCustomException() {
        // Make the dependency throw CustomException twice (initial call + retry)
        when(fileSystemFactory.someMethodThatThrowsException())
                .thenThrow(new CustomException("Test trigger"))
                .thenThrow(new CustomException("Test trigger"));

        // Expect the final call to still throw (since we're retrying once, not swallowing the exception)
        Assertions.assertThrows(CustomException.class, () -> {
            storeFiles.storeFiles(conn, first, second, third, fourth);
        });

        // Verify the dependency was called twice—confirms retry logic worked
        verify(fileSystemFactory, times(2)).someMethodThatThrowsException();
    }
}

Key Takeaways:

  1. Never mock the class you're testing: You need the real StoreFiles instance running so your custom retry annotation's logic (aspect/proxy) can execute. Only mock its dependencies.
  2. Trigger the exception via dependencies: Your retry logic kicks in when CustomException is thrown—make sure the dependency method that causes this exception is mocked to throw it the right number of times (matches your retry count + 1 initial call).
  3. Verify dependency calls, not the tested method: Since the retry is internal to the StoreFiles instance, Mockito/JMockit won't count multiple invocations of storeFiles() itself. Instead, check that the dependency method (the one that throws the exception) was called the expected number of times.

If your custom retry annotation uses an aspect (like Spring AOP), ensure that aspect is active in your test context—for example, adding @EnableAspectJAutoProxy if you're using Spring.

内容的提问来源于stack exchange,提问作者Drew13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:55:27