将 REST controller/route 添加到 Spring Boot 测试
Add REST controller/route to SpringBoot test
是否可以将 route/endpoint(我不想将其包含在源代码中,而是将其留在测试中)添加到 SpringBoot 测试中?
@RestController
class HelloAPI {
@GetMapping("/hello")
public String ok() {
return "world";
}
}
更新:
事实证明不需要额外的配置 - HelloAPI
class 应该从 src/main
移动到 src/test
。而已。但是,对于所有@SpringBoot 测试,它将是 "visible"。
所以问题是:如何将此 bean (HelloAPI) 的创建(在 ApplicationContext 中注册)限制为特定测试 class?
您可以添加静态 inner @Configuration
class 来设置 bean:
@RunWith(SpringRunner.class)
... // Other test annotations
public class YourTestClass {
@Configuration
static class ContextConfiguration {
@Bean
public HelloAPI helloAPI() {
return new HelloAPI();
}
}
@Test
public void someTest_shouldXxx() { ... }
}
并确保在 /src/test
中添加 HelloAPI
class 而不是 /src/main/
。
但是请注意,(test)ApplicationContext
将在执行完 class 中的所有测试后被销毁,从而也销毁 HelloAPI
bean。
如果您正在寻找向 RestTemplate
提供 test-endpoints 的方法,请将 MockRestServiceServer
绑定到您的 RestTemplate
instead.
您可以为此使用 @TestConfiguration
:
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT)
class EmbeddedApiTest {
@Test
void testSomething() {
...
}
@TestConfiguration
public static class TestCfg {
@RestController
@RequestMapping("/test")
public class TestApi {
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}
}
}
虽然我已经接受了 Anatoliy 的回答(他正在使用 Java 和 JUnit5),但我想分享我的 Kotlin 代码(使用旧的 JUnit4):
@RunWith(SpringRunner::class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
class TestWithInnerConfigTest {
@LocalServerPort var port: Int? = null
@Autowired private lateinit var restTemplate: TestRestTemplate
@Test
fun testingMainEndpoint() {
val url = "http://localhost:$port/helloworld"
val resp = restTemplate.exchange(url, GET, null, String::class.java)
assertEquals(resp.statusCode, OK)
}
@Test
fun testingTestEndpoint() {
val url = "http://localhost:$port/test"
val resp = restTemplate.exchange(url, GET, null, String::class.java)
assertEquals(resp.statusCode, NOT_FOUND)
}
companion object {
@TestConfiguration
class TestCfg {
@RestController
class TestApi {
@GetMapping("/test") fun hello() = "Helloworld!"
}
}
}
}
使用静态内部 @TestConfiguration
class 的好处是它仅应用于此文件。这是 link to the complete example.
是否可以将 route/endpoint(我不想将其包含在源代码中,而是将其留在测试中)添加到 SpringBoot 测试中?
@RestController
class HelloAPI {
@GetMapping("/hello")
public String ok() {
return "world";
}
}
更新:
事实证明不需要额外的配置 - HelloAPI
class 应该从 src/main
移动到 src/test
。而已。但是,对于所有@SpringBoot 测试,它将是 "visible"。
所以问题是:如何将此 bean (HelloAPI) 的创建(在 ApplicationContext 中注册)限制为特定测试 class?
您可以添加静态 inner @Configuration
class 来设置 bean:
@RunWith(SpringRunner.class)
... // Other test annotations
public class YourTestClass {
@Configuration
static class ContextConfiguration {
@Bean
public HelloAPI helloAPI() {
return new HelloAPI();
}
}
@Test
public void someTest_shouldXxx() { ... }
}
并确保在 /src/test
中添加 HelloAPI
class 而不是 /src/main/
。
但是请注意,(test)ApplicationContext
将在执行完 class 中的所有测试后被销毁,从而也销毁 HelloAPI
bean。
如果您正在寻找向 RestTemplate
提供 test-endpoints 的方法,请将 MockRestServiceServer
绑定到您的 RestTemplate
instead.
您可以为此使用 @TestConfiguration
:
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT)
class EmbeddedApiTest {
@Test
void testSomething() {
...
}
@TestConfiguration
public static class TestCfg {
@RestController
@RequestMapping("/test")
public class TestApi {
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}
}
}
虽然我已经接受了 Anatoliy 的回答(他正在使用 Java 和 JUnit5),但我想分享我的 Kotlin 代码(使用旧的 JUnit4):
@RunWith(SpringRunner::class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
class TestWithInnerConfigTest {
@LocalServerPort var port: Int? = null
@Autowired private lateinit var restTemplate: TestRestTemplate
@Test
fun testingMainEndpoint() {
val url = "http://localhost:$port/helloworld"
val resp = restTemplate.exchange(url, GET, null, String::class.java)
assertEquals(resp.statusCode, OK)
}
@Test
fun testingTestEndpoint() {
val url = "http://localhost:$port/test"
val resp = restTemplate.exchange(url, GET, null, String::class.java)
assertEquals(resp.statusCode, NOT_FOUND)
}
companion object {
@TestConfiguration
class TestCfg {
@RestController
class TestApi {
@GetMapping("/test") fun hello() = "Helloworld!"
}
}
}
}
使用静态内部 @TestConfiguration
class 的好处是它仅应用于此文件。这是 link to the complete example.