I implemented resilience4j in my project using the Spring Boot2 starter (https://resilience4j.readme.io/docs/getting-started-3).
I annotated a method with @CircuitBreaker that uses http client for calling an external service and the circuit breaker is working fine - including its fallback.
I'd like to add unit tests for it but when I run a test trying to simulate the fallback, nothing happens - the exception is thrown but is not handled by the circuit breaker mechanism.
I've found some examples using its metrics but it is not useful in my case.
Any thoughts?
Here is a snippet of my client:
@CircuitBreaker(name = "MY_CICUIT_BREAKER", fallbackMethod = "fallback")
public ResponseEntity<String> search(String value) {
ResponseEntity<String> responseEntity = restTemplate.exchange(
searchURL,
HttpMethod.GET,
new HttpEntity(new HttpHeaders()),
String.class,
value);
}
public ResponseEntity<String> fallback(String value, ResourceAccessException ex) {
return "fallback executed";
}
As andres and pvpkiran mentioned/explained, I had to add a integration test.
You can achieve that basically adding @SpringBootTest annotation to your test class, it will bootstrap a container with spring context on it.
I also autowired CircuitBreakerRegistry in order to reset the circuit breaker before each test so I could guarantee a clean test. For mocking/spying/verifying I used Mockito from spring boot test starter (spring-boot-starter-test).
Here is how I managed to test the fallbacks methods:
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class RestClientIntegrationTest {
private final String SEARCH_VALUE = "1234567890";
@MockBean( name = "myRealRestTemplateName")
private RestTemplate restTemplate;
@SpyBean
private MyRestClient client;
@Autowired
private CircuitBreakerRegistry circuitBreakerRegistry;
@BeforeEach
public void setUp() {
circuitBreakerRegistry.circuitBreaker("MY_CIRCUIT_BREAKER_NAME").reset();
}
@Test
public void should_search_and_fallback_when_ResourceAccessException_is_thrown() {
// prepare
when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class), eq(SEARCH_VALUE)))
.thenThrow(ResourceAccessException.class);
String expectedResult = "expected result when fallback is called";
// action
String actualResult = client.search(SEARCH_VALUE);
// assertion
verify(client).fallback(eq(SEARCH_VALUE), any(ResourceAccessException.class));
assertThat(actualResult, is(expectedResult));
}
}
I hope there is no compilation error since I had to remove some non-relevant stuff.