I'm attempting to unit test a resilience4j CircuitBreaker, and according to the documentation and my testing, I need to utilize the @SpringBootTest
annotation in order to correctly instantiate the circuit breaker for the unit test.
When I attempt to run the unit test I am receiving a UnsatisfiedDependencyException when it tries to instantiate a downstream bean because the value of the property instead of being "true" or "false" is the string value of the property ${boolean.property:true}
instead of when I normally run the project manually it is just true
.
My unit test is as follows (I am using JUnit 5 and Spring Boot 2.6.6)
@SpringBootTest(classes = Application.class)
class CircuitBreakerTest {
@MockBean
private Webservice webservice;
private final Handler handler = new Handler();
@Test
public void testChangeMatrixCircuitBreaker() {
when(webservice.process(any())).thenThrow(new RuntimeException());
for (int i = 0; i < 11; i++) {
// circuit breaker should trip after 10 failures
ResponseEntity response = handler.processClientRequest("id", "<body/>");
if (i > 9) {
assertTrue("CircuitBreaker tripped".equals((String) response.getBody()));
}
}
}
}
Application.java
@SpringBootApplication
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
@ImportResource({"classpath:serviceContext.xml"})
@ComponentScan({"application.foundation", "config"})
public class Application {
private static final Logger LOGGER = LogManager.getLogger(AISApplication.class);
public static void main(String[] args) {
SpringApplication.run(AISApplication.class, args);
}
@PreDestroy
public void tearDown() {
LOGGER.info("PreDestroy - Shutting Down");
}
}
The bean that is causing the exception is defined inside of the application.foundation
component scan. More exactly inside of the resource that it imports.
package application.foundation.security;
@Configuration
@ImportResource({ "classpath:securedClientContext.xml" })
public class OutboundSecurityConfiguration {
...
}
securedClientContext.xml (note that I do not have the ability to change this file)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="beanIDontControl" class="bean.i.dont.control.security.BeanIDontControlBean">
<constructor-arg name="unique" value="${boolean.property:true}" />
</bean>
</beans>
The stack trace is as follows:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'beanIDontControl' defined in class path resource [securedClientContext.xml]:
Unsatisfied dependency expressed through constructor parameter 0: Could not convert argument value of type [java.lang.String] to required type [boolean]:
Failed to convert value of type 'java.lang.String' to required type 'boolean'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [${boolean.property:true}]
It's failing on line 761 of ContructorResolver
// when i unit test originalValue = ${boolean.property:true} when i run normally it is just true
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
Does anyone know a way that I could possibly mock or ignore this bean? Maybe even ignore the whole component scale of that security package? I've tried use @TestConfiguration, I've tried everything around @TestPropertySource, I've tried using the property field within @SpringBootTest to manually set the values, no matter what I do I cannot see a change in that property.