As a unit testing framework for Java programming language, Junit actually plays an important role in test-driven development to test a Spring application. To test the interactions between Spring and your code, you will need Spring Boot.
Unfortunately, when you are working with Spring Boot apps, you will likely find the error message that says ‘Failed to load ApplicationContext’. If you get this error, you may wonder why it occurs and what you should do to fix the error message. Let’s find out the guide to fix this error message through our post below!
What is the Cause of ‘Failed to load ApplicationContext’ Error Message?
When you want to use the XML Based configuration in the test classes, sometimes you may face the application context loading error that says ‘Failed to Load ApplicationContext’. Commonly, this error will appear in the test classes since the application context is not loaded in the test context.
To prove it, we can try to reproduce the error by integrating XML-Based application context in a Spring Boot application. First, assuming that we have an application-context.xml file with the definition of a service bean:
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=” http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>
<bean id=”employeeServiceImpl” class=”com.baeldung.xmlapplicationcontext.service.EmployeeServiceImpl” /> </beans> |
Now, you can try to add the application-context.xml file in the webapp/WEB-INF/ location by heading toward Webapp à WEB-INF à application-context.xml.
Then, you can try to create a service interface and class:
public interface EmployeeService {
Employee getEmployee(); } public class EmployeeServiceImpl implements EmployeeService { @Override public Employee getEmployee() { return new Employee(“Baeldung”, “Admin”); } } |
Last, you can create a test care for getting the EmployeeService bean from the application context:
@RunWith(SpringRunner.class)
@ContextConfiguration(locations={“classpath:WEB-INF/application-context.xml”}) public class EmployeeServiceAppContextIntegrationTest { @Autowired private EmployeeService service; @Test public void whenContextLoads_thenServiceISNotNull() { assertThat(service).isNotNull(); }
} |
Then, if you try running this test, you will find the error message as follow:
java.lang.IllegalStateException: Failed to load ApplicationContext |
Well, we have proven that the error appears in the test classes, since the application context is not loaded in the test context. Furthermore, the root cause is that the WEB-INF is not included in the classpath:
@ContextConfiguration(locations={“classpath:WEB-INF/application-context.xml”}) |
How to Fix ‘Failed to Load ApplicationContext’ Error Message?
There are a number of sources that inform the guide to fix this error message. The first method is from jvt.me that describes starting a new Spring Boot project or picking up an existing one which does not have the test. The test that the source uses is:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest // you could use `@ActiveProfiles`, too class ApplicationIntegrationTest {
@Test void contextLoads() { // empty test that would fail if our Spring configuration does not load correctly } } |
This script actually validates that Spring’s context will be configured correctly for the application and ensures you have obtained things like bean/property definitions. However, the test above is not perfect, as it will bring you the ‘fail status’ again before it executes if the context is not set.
You can try to obtain the test passing incorrectly by putting it into the wrong package or also clearing out the Spring Boot Configuration:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.boot.test.context.SpringBootTest;
-@SpringBootTest class ApplicationIntegrationTest {
@Test void contextLoads() { // empty test that would fail if our Spring configuration does not load correctly } } |
It will allow the empty test case to silently continue to pass, while the application is broken. You can also improve what you have got to the following test case instead:
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext;
@SpringBootTest class ApplicationIntegrationTest { @Test void contextLoads(ApplicationContext context) { assertThat(context).isNotNull(); } } |
Well, it will ensure that you have got the context and it has been set up successfully. In the test case above, where you omit the @SpringBootTest’ , the test will fail at all. When using Junit5, the ‘ApplicationContext’ will be injected automagically. However, you can replace it with an ‘@Autowired’ field too.
You can also try to validate that specific beans are instantiated, for instance checking that there is a bean for class ‘IndieAuthController’:
@Test
void hasIndieAuthControllerConfigured(ApplicationContext context) { assertThat(context.getBean(AccessTokenVerifier.class)).isNotNull(); } |
Or for a specific bean’s name, for example ‘@Qualifier’:
@Test
void hasIndieAuthControllerConfigured(ApplicationContext context) { assertThat(context.getBean(“accessTokenVerifier”)).isNotNull(); } |
Another source also gives a guide to solve the error message that says ‘Failed to Load ApplicationContext’ when working with Junit Spring Boot. We also got the guide from Baeldung.com.
This site actually gives you 3 methods to fix the ‘Failed to Load ApplicationContext’ error message when working with Junit Spring Boot. Here are they:
1. Using @SpringBootTest and @ImportResource
To use it, you can firstly use @ImportResource annotation in the main class:
@SpringBootApplication
@ImportResource({“classpath*:application-context.xml”}) |
Now, you can try to create a test case to get EmployeeService bean from the application context:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = XmlBeanApplication.class) public class EmployeeServiceAppContextIntegrationTest {
@Autowired private EmployeeService service;
@Test public void whenContextLoads_thenServiceISNotNull() { assertThat(service).isNotNull(); }
} |
Well, the @ImportResource annotation will load XML beans that are located in the resource directory. @SpringBootTest annotation will also load the whole application’s beans in the test class. You can also access the EmployeeService bean in the test class.
2. Using @ContextConfiguration with Resources
You can also create your test context with different configuration of beans by putting your test configuration file in the src/test/resources directory. You can als use the @ContextConfiguration annotation to load the test context from the src/test/resources directory.
You can create another bean from the EmployeeService Interface:
public class EmployeeServiceTestImpl implements EmployeeService {
@Override public Employee getEmployee() { return new Employee(“Baeldung-Test”, “Admin”); } } |
Then, make sure to create the test-context.xml file in the src/test/resources directory, here it is:
<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd”>
<bean id=”employeeServiceTestImpl” class=”process.service.EmployeeServiceTestImpl” /> </beans> |
Last, you can create the test case:
@SpringBootTest
@ContextConfiguration(locations = “/test-context.xml”) public class EmployeeServiceTestContextIntegrationTest {
@Autowired @Qualifier(“employeeServiceTestImpl”) private EmployeeService serviceTest;
@Test public void whenTestContextLoads_thenServiceTestISNotNull() { assertThat(serviceTest).isNotNull(); }
} |
Here, you have loaded employeeServiceTestimpl from the test-context.xml using the @ContextConfiguration annotation.
3. Using @ContextConfiguration with WEB-INF
Last, you can also try to import an application context in the test classes from the WEB-INF directory. To do so, you can address the application context using its file URL. Here it is:
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = “file:src/main/webapp/WEB-INF/application-context.xml”) |
AUTHOR BIO
On my daily job, I am a software engineer, programmer & computer technician. My passion is assembling PC hardware, studying Operating System and all things related to computers technology. I also love to make short films for YouTube as a producer. More at about me…
Leave a Reply