spring - 为什么我无法将 Controller 实例 Autowiring 到此 Spring Boot 应用程序的 JUnit 类中?找不到@SpringBootConfiguration

标签 spring junit spring-boot

我正在开发我的第一个 Spring Boot 应用程序,并且在尝试使用 JUnit 测试我的 Controller 类时发现一些困难。

所以我有以下情况,这是我名为 PlaceSearcherController 的 Controller 类:

@RestController
@RequestMapping("/PlaceSearcher")
public class PlaceSearcherController {

    private static final Logger log = LoggerFactory.getLogger(PlaceSearcherController.class);


    @Autowired
    private MainSearchServices mainSearchServices;

    @RequestMapping(value = "hello")
    public String hello() {
        return "Hello World";
    }

    @RequestMapping(value = "",
            method = RequestMethod.GET)
    public ResponseEntity<String> home() {
        List<AccomodationDTO> accomodationDTOs = new ArrayList<>();

        return ResponseEntity.ok("c è figa");
    }

    @RequestMapping(value = "getBestListHotel",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<AccomodationDTO>> getHolteListFromPlace(@Valid @RequestBody MainSearchListHotelVO searchObject) {
        List<AccomodationDTO> accomodationDTOs = new ArrayList<>();

        log.debug("search vo in input: " + searchObject);
        try {
            accomodationDTOs = mainSearchServices.getBestHotelListFromPlace(searchObject);
        } catch (Exception e) {
            log.error("Exception: ", e);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
        }

        if (accomodationDTOs.isEmpty()) {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null);
        }

        return ResponseEntity.ok(accomodationDTOs);
    }

    @RequestMapping(value = "getHotelById",
            method = RequestMethod.GET,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<AccomodationDTO> getHoltelById( Integer id ) {
        AccomodationDTO accomodationDTO = null;

        try {
            accomodationDTO = mainSearchServices.getHotelFromId(id);
        } catch (Exception e) {
            log.error("Exception: ", e);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
        }

        if ( accomodationDTO==null ) {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null);
        }

        return ResponseEntity.ok(accomodationDTO);
    }

    @RequestMapping(value = "getListRoomByHotelId",
            method = RequestMethod.GET,
            consumes = MediaType.APPLICATION_JSON_VALUE,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<List<RoomDTO>> getListRoomByHotelId( Integer hotelId ) {
        List<RoomDTO> roomDTOs = null;

        try {
            roomDTOs = mainSearchServices.getListRoomByHotelId(hotelId);
        } catch (Exception e) {
            log.error("Exception: ", e);
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
        }

        if ( roomDTOs==null ) {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null);
        }

        return ResponseEntity.ok(roomDTOs);
    }

}

然后我有一个名为 PlaceSearcherControllerTest 的 JUnit 测试类,其中包含以下代码:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class PlaceSearcherControllerTest {

    @Autowired
    private PlaceSearcherController placeSearcherController;

    @Test
    public void placeSearcherControllerTest() {
        System.out.println("placeSearcherControllerTest START");
        System.out.println("placeSearcherControllerTest END");
    }

}

此时,placeSearcherControllerTest() 方法什么也不做,我只是尝试运行定义在 JUnit 类中的 JUnit 测试方法,以获取 PlaceSearcherController Controller 实例。

所以问题是,运行之前的 placeSearcherControllerTest() 测试方法时,我收到以下错误消息:

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

    at org.springframework.util.Assert.state(Assert.java:392)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.getOrFindConfigurationClasses(SpringBootTestContextBootstrapper.java:173)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:133)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:409)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:323)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:277)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:112)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:78)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:120)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:105)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:152)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:143)
    at org.springframework.test.context.junit4.SpringRunner.<init>(SpringRunner.java:49)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:96)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)


Process finished with exit code -1

这是为什么呢?如何解决此问题并正确获取 PlaceSearcherController 实例到我的 JUnit 测试类中?

错误消息告诉我:

Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

这些@SpringBootConfiguration@ContextConfiguration@SpringBootTest是什么?

在这里阅读:http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringBootConfiguration.html在我看来,@SpringBootConfiguration可用于提供bean定义(作为Spring中的@Configuration类,不使用Spring Boot)。

我的测试类用 @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) 进行注释,并在此处阅读:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html它说:

Spring Boot provides a @SpringBootTest annotation which can be used as an alternative to the standard spring-test @ContextConfiguration annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests via SpringApplication

所以我认为我有来自 Controller 实例的应用程序上下文。我该如何解决?我认为我错过了一些东西,并且解决方案必须非常简单,因为我只有一个 Controller 类和测试类。

最佳答案

假设您的 Controller 位于 com.example.foo.controller 中,并且您的测试位于同一目录中。现在,我们假设您的主类(您的 @SpringBootApplication)位于 com.example.foo.app 中。由于您的设置不寻常,您可能已经调整了组件扫描指令。

这也会对测试产生影响!测试支持将尝试通过在父包中查找来查找 @SpringBootConfiguration (@SpringBootApplication@SpringBootConfiguration)一场比赛。如果没有,它将抛出此异常。

key 是this section of the doc

The search algorithm works up from the package that contains the test until it finds a @SpringBootApplication or @SpringBootConfiguration annotated class. As long as you’ve structured your code in a sensible way your main configuration is usually found.

因此它在 com.example.foo.controller 中搜索此类匹配,然后在 com.example.foo 中搜索 com.example 然后 com。最终它放弃并抛出异常。

您尚未在 @SpringBootTest 中给出上下文,因此它不知道要启动什么上下文。尝试在其中添加对您的 @SpringBootApplication 的引用,例如:

@SpringBootTest(classes = MyApp.class, webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)

如果我的假设是正确的,我强烈建议您检查您的包结构。

关于spring - 为什么我无法将 Controller 实例 Autowiring 到此 Spring Boot 应用程序的 JUnit 类中?找不到@SpringBootConfiguration,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40260489/

相关文章:

java - 我已允许 @CrossOrigin(origins ="*") 注释,但它仍然不起作用。谁能告诉我这里出了什么问题吗?

java - 数据传输对象 DTO 在哪里构建

android - 使用 Robolectric 在两个(或更多)Android 版本上运行 Android 测试

java - 为什么 Mockito.when(...).thenThrow(...) 直接抛出错误

java - Spring WS : How to get and save XSD validation errors

spring - 如何使用 Spring 和 Hibernate 在项目中通过 PowerMockito 模拟 SessionFactory 或 Session?

java - Log4J2 属性替换 - 使用外部属性文件

java - 在作为 jar/war 运行的 Spring Boot 应用程序中,JAXB 解码非常慢

java - Spring Boot 不从 yml 文件中读取数据库配置

java - 将 @PathVariable 传递到我的所有 JSP 页面而不将其添加到 ModelAndView 的最佳方法是什么?