我正在开发我的第一个 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
)一场比赛。如果没有,它将抛出此异常。
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/