Tengo un controlador de arranque de resorte simple y quiero escribir una prueba unitaria para él, pero hay un error. He buscado en Google durante horas, pero todavía no puedo encontrar la solución. Aquí está el código:

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";
    }
}

Y archivo de prueba de unidad: 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"));
    }

}

Pero hay un 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

Alguien puede ayudarme ? Solo soy un novato en la bota Spring

0
Thach Huynh 14 ene. 2018 a las 10:09

3 respuestas

La mejor respuesta

Tuve un problema similar. Por favor vea el código a continuación:

@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());

}

Vea a continuación la ejecución del caso de prueba:

Test Case Image

Verifique las anotaciones que utilizó, es decir: 1) @RunWith (SpringRunner.class) 2) @SpringBootTest 3) @AutoConfigureMockMvc

6
Shashank Bodkhe 2 ago. 2018 a las 20:48

Para cualquiera que tenga el mismo problema: es importante usar @MockBean. (@Mock no lo cortará)

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

Usamos @MockBean para crear e inyectar un simulacro para GreetingService (si no lo hace, el contexto de la aplicación no puede iniciarse), y establecemos sus expectativas con Mockito.

Por lo tanto, es probable que todo haya estado bien si OP acaba de reemplazarse

@Mock
private HelloService helloService;

Con

@MockBean
private HelloService helloService;

Por lo tanto, las anotaciones de clase adicionales de la respuesta aceptada no deberían ser necesarias

0
Bob 17 abr. 2020 a las 01:43

Lo que falta aquí es la anotación @SpringBootTest. Esta anotación se utiliza para cargar las clases @Configuration para probar e iniciar el contenedor incrustado con el puerto predeterminado.
Si no se especifica una clase @Configuration, usaría la clase predeterminada @SpringBootApplication, ya que tiene @Configuration dentro de su anotación.

0
Bilal Abdulkany 16 ago. 2018 a las 05:52