spring-cloud-circuitbreaker: Spring Boot 2 + resilience4j - fallback method not being called in integration test
I originally asked this as an SO question and then as in issue in the resilience4j project, and RobWin pointed me over here. To save clicks, I’ll copy-paste the full text of the GH issue below.
=== START COPY-🍝 ===
Resilience4j version: 1.7.0
Spring Cloud Starter version: 2.1.0
Java version: 17
I posted an SO question laying out my problem. Initially, I couldn’t get the CB instance from the registry, but I solved that issue by importing CircuitBreakerAutoConfiguration.class. Now, the other issue is that the fallback method isn’t being invoked. It works when the code is deployed but not in the integration test. I verified by debugging in my IDE that the CB is being created, with the configs I have defined in a test YAML.
resilience4j:
circuitbreaker:
instances:
pmiServiceCircuitBreaker:
minimumNumberOfCalls: 5
slidingWindowSize: 10
slidingWindowType: COUNT_BASED
failureRateThreshold: 50 # percentage
slowCallRateThreshold: 100 # percentage for slowCallDurationThreshold
slowCallDurationThreshold: 200ms # milliseconds, should this be lower?
permittedNumberOfCallsInHalfOpenState: 5
waitDurationInOpenState: 1s # seconds
The simple test looks like:
@slf4j
https://github.com/import(
{
TestConfig.class,
CircuitBreakerAutoConfiguration.class
}
)
https://github.com/SpringBootTest(
classes = {
GrpcTestServer.class,
TestGrpcClientConfigSpy.class,
ClassWithCircuitBreaker.class
}
)
@activeprofiles("test")
@ExtendWith(SpringExtension.class)
@testinstance(TestInstance.Lifecycle.PER_CLASS)
public class ClassWithCircuitBreakerTest {
@Autowired
private TestGrpcClientConfigSpy grpcClientConfigSpy;
@Autowired
CircuitBreakerRegistry circuitBreakerRegistry;
@SpyBean
@Autowired
ClassWithCircuitBreaker cwcb;
@DisplayName("ClassWithCircuitBreaker - circuit breaker enabled")
@Test
void testCircuitBreaker_enabled() throws IOException {
circuitBreakerRegistry.getAllCircuitBreakers().forEach(cb -> {
log.info("found circuit breaker :: {}", cb.getName());
log.info("circuit breaker state is :: {}", cb.getState().name());
});
int failedCalls = 0;
Stream.rangeClosed(1,10).forEach(count -> {
try {
cwcb.doStuff("blah", "test-id-123");
} catch(StatusRuntimeException sre) {
log.warn("exceptiones? {}", sre.getMessage());
};
});
CircuitBreaker cb = circuitBreakerRegistry.circuitBreaker("myCB");
CircuitBreaker.Metrics metrics = cb.getMetrics();
log.info("configs :: {}", cb.getCircuitBreakerConfig());
log.info("failed metrics :: {}", metrics.getNumberOfFailedCalls());
log.info("success metrics :: {}", metrics.getNumberOfSuccessfulCalls());
log.info("state after test :: {}", cb.getState().name());
assertTrue(true);
}
}
The class I am testing is a gRPC client, so the GrpcTestServer class sets up a server and for this test, it’s configured to throw a StatusRuntimeException and I see that being logged in the test, but the fallback method is never invoked, and all of the metrics are zero and the circuit stays closed. Again, this works when deployed, it’s only the integration test that is not working. Any help is much appreciated.
=== END COPY-🍝 ===
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 17 (4 by maintainers)
Can you provide a complete, minimal, verifiable sample that reproduces the problem? It should be available as a GitHub (or similar) project or attached to this issue as a zip file.