带重试逻辑方法的单元测试:验证异常触发重试
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
StoreFileswithMockito.mock(StoreFiles.class), callingstoreFiles()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
@Testedinstance, you're probably not properly mocking your dependencies to throw theCustomExceptionthat 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:
- Never mock the class you're testing: You need the real
StoreFilesinstance running so your custom retry annotation's logic (aspect/proxy) can execute. Only mock its dependencies. - Trigger the exception via dependencies: Your retry logic kicks in when
CustomExceptionis 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). - Verify dependency calls, not the tested method: Since the retry is internal to the
StoreFilesinstance, Mockito/JMockit won't count multiple invocations ofstoreFiles()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
相关产品推荐
相关产品推荐

