Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot controller unit test : Failed to load ApplicationContext

I have a simple spring boot controller and I want to write unit test for it but there is an error. I've googled for hours but still cannot find the solution. Here is code:

HelloController.java

@RestController
public class HelloController {

    @Autowired
    private HelloService helloService;

    @GetMapping("/hello")
    public String sayHello(){
        return helloService.sayHello();
    }
}

HelloService.java:

@Service
public class HelloService {
    public String sayHello(){
        return "Hello";
    }
}

And unit test file: HelloControllerTest.java:

@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Mock
    private HelloService helloService;

    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void sayHello() throws Exception {
        when(helloService.sayHello()).thenReturn("thach");
        mockMvc.perform(get("/hello"))
                .andExpect(status().isOk())
                .andExpect(content().string("thach"));
    }

}

But there is an error:

java.lang.IllegalStateException: Failed to load ApplicationContext

    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:122)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:105)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:74)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:312)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:284)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.IllegalArgumentException: Cannot load an ApplicationContext with a NULL 'contextLoader'. Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.
    at org.springframework.util.Assert.notNull(Assert.java:134)
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:57)
    at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
    ... 24 more

Can any one help me ? I am just a newbie to Spring boot

like image 516
Thach Huynh Avatar asked Oct 18 '25 17:10

Thach Huynh


2 Answers

I had similar issue. Please see code below:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ApplicationControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockBean
    ApplicationService applicationService;

    @Test
    public void testGetImagePath() throws Exception {

        RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/application/get-image")
                .contentType(MediaType.IMAGE_GIF);

        MvcResult result = mockMvc.perform(requestBuilder).andReturn();
        System.out.println(result.getResponse());
    }
}

Please see below test case execution:

Test Case Image

Check Annotations you used i.e. :

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. @AutoConfigureMockMvc
like image 108
Shashank Bodkhe Avatar answered Oct 20 '25 07:10

Shashank Bodkhe


For anyone that runs into the same issue - It is important to use @MockBean. (@Mock won't cut it)

See https://spring.io/guides/gs/testing-web/:

We use @MockBean to create and inject a mock for the GreetingService (if you do not do so, the application context cannot start), and we set its expectations using Mockito.

So it is likely all may have been fine if OP just replaced

@Mock
private HelloService helloService;

with

@MockBean
private HelloService helloService;

So the additional class annotations from the accepted answer should not be necessary

like image 28
Adam Avatar answered Oct 20 '25 07:10

Adam