Spring Boot / Jersey在应用程序启动并从测试访问时找不到处理程序方法。如果我单独启动应用程序并使用浏览器访问http://localhost:8080/demo
,一切都很好。
日志说:"没有为[/ demo]"找到处理程序方法。相关的日志输出:
2018-06-18 17:04:31.071 DEBUG 7628 --- [nio-8080-exec-1] o.s.web.reactive.DispatcherHandler : Processing GET request for [http://localhost:8080/demo]
2018-06-18 17:04:31.083 DEBUG 7628 --- [nio-8080-exec-1] s.w.r.r.m.a.RequestMappingHandlerMapping : Looking up handler method for path /demo
2018-06-18 17:04:31.085 DEBUG 7628 --- [nio-8080-exec-1] s.w.r.r.m.a.RequestMappingHandlerMapping : Did not find handler method for [/demo]
2018-06-18 17:04:31.087 DEBUG 7628 --- [nio-8080-exec-1] o.s.w.r.handler.SimpleUrlHandlerMapping : Matching pattern for request [[path='/demo']] is /**
该应用程序包含以下类(用Kotlin编写):
资源
import org.springframework.stereotype.Component
import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.core.Response
@Component
@Path("/")
class Resource {
@GET
@Path("demo")
fun test() = Response.ok("Hi!").encoding("UTF-8").build()
}
JerseyConfig
import org.glassfish.jersey.server.ResourceConfig
import org.springframework.stereotype.Component
@Component
class JerseyConfig : ResourceConfig() {
init {
register(Resource::class.java)
}
}
应用:
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class App
fun main(args: Array<String>) {
runApplication<App>(*args)
}
失败的测试:
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit.jupiter.SpringExtension
import org.springframework.test.web.reactive.server.WebTestClient
@ExtendWith(SpringExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class ResourceTest {
@Autowired
lateinit var client: WebTestClient
@Test
fun getTest() {
client.get().uri("demo").exchange().expectStatus().isOk
}
}
如果我使用Jersey客户端进行测试,我会得到同样的错误:
@Test
fun testWithJersey() {
val client = ClientBuilder.newClient()
val response = client.target("http://localhost:8080/demo").request().get()
assertThat(response.status).isEqualTo(200)
}
的build.gradle:
buildscript {
ext {
kotlinVersion = '1.2.50'
springBootVersion = '2.0.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
}
}
apply plugin: 'kotlin'
apply plugin: 'kotlin-spring'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
compileKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
compileTestKotlin {
kotlinOptions {
freeCompilerArgs = ["-Xjsr305=strict"]
jvmTarget = "1.8"
}
}
repositories {
mavenCentral()
}
dependencies {
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
compile("org.jetbrains.kotlin:kotlin-reflect")
compile('org.springframework.boot:spring-boot-starter-jersey')
testCompile("org.springframework.boot:spring-boot-starter-test") {
exclude group: "junit", module: "junit"
}
testCompile('org.springframework.boot:spring-boot-starter-webflux')
testCompile("org.junit.jupiter:junit-jupiter-api")
testRuntime("org.junit.jupiter:junit-jupiter-engine")
}
测试代码本身似乎没问题,因为当我用Thread.sleep(...)
替换测试方法的主体然后从浏览器访问服务器时,我得到相同的错误(404由于&#34;没有为[/ demo]&#34;)找到处理程序方法。
为什么在测试中找不到处理程序方法?我需要改变什么?
答案 0 :(得分:1)
您确定WebTestClient
是一个通用客户端(它会产生实际的网络请求),而不仅仅意味着像MockMvc
这样的Spring MVC一起使用吗?该错误听起来像是在寻找Spring MVC处理程序方法。如果它是一个通用客户端,那么错误消息就不会说出处理程序方法的任何内容,而是可能会对URL进行说明。
我认为您需要与真实客户端进行实际的网络请求。例如,如果您使用Jersey客户端,则可以执行类似
的操作@LocalServerPort
private int port;
private Client client = ClientBuilder.newClient();
@Test
public void testCustomerLocationOnPost() {
URI resourceUri = UriBuilder.fromUri("http://localhost")
.port(port).path("demo").build();
Respons response = client.target(resourcrUri).request().get();
assertThat(response.getStatus()).isEqualTo(200);
}
答案 1 :(得分:1)
在Pivotal的神奇人物的帮助下,我解决了这个问题:WebTestClient
需要WebFlux
作为依赖。但是,WebFlux不仅带来了一个小测试助手,而且还带来了一个完整的Web框架,它由Spring Boot自动配置,与Jersey相冲突。
解决方案是从依赖项中删除WebFlux
dependencies {
compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
compile("org.jetbrains.kotlin:kotlin-reflect")
compile('org.springframework.boot:spring-boot-starter-jersey')
testCompile("org.springframework.boot:spring-boot-starter-test") {
exclude group: "junit", module: "junit"
}
testCompile("org.junit.jupiter:junit-jupiter-api")
testRuntime("org.junit.jupiter:junit-jupiter-engine")
}
并使用例如Jersey http客户端:
@ExtendWith(SpringExtension::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class ResourceTest {
@Test
fun testWithJerseyClient() {
val client = ClientBuilder.newClient()
val response = client.target("http://localhost:8080/demo").request().get()
assertThat(response.status).isEqualTo(200)
}
}
但只要WebFlux不是依赖项,任何其他http客户端都会这样做。
更新:这是Spring Boot中的一个错误,它将在Spring Boot 2.0.4中修复!然后,您可以使用WebFlux与服务器端的Jersey一起进行测试。