Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 测试中未找到Spring Boot中带有Jersey的处理程序方法_Java_Spring Boot_Jersey_Spring Webflux_Spring Jersey - Fatal编程技术网

Java 测试中未找到Spring Boot中带有Jersey的处理程序方法

Java 测试中未找到Spring Boot中带有Jersey的处理程序方法,java,spring-boot,jersey,spring-webflux,spring-jersey,Java,Spring Boot,Jersey,Spring Webflux,Spring Jersey,当应用程序是startet并通过测试访问时,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

当应用程序是startet并通过测试访问时,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()
}
球衣

import org.glassfish.jersey.server.ResourceConfig
import org.springframework.stereotype.Component

@Component
class JerseyConfig : ResourceConfig() {

    init {
        register(Resource::class.java)
    }
}
应用程序:

如果我使用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原因是“没有找到[/demo]的处理程序方法”)


为什么在测试中找不到处理程序方法?我必须改变什么?

你确定
WebTestClient
是一个通用客户端(发出实际的网络请求),而不仅仅是用于Spring-MVC,比如
MockMvc
吗?这个错误听起来像是在寻找SpringMVC处理程序方法。如果它是一个通用客户机,那么错误消息不会显示任何关于处理程序方法的信息,而是可能会显示一些关于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);

}

在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中的一个bug,将在Spring Boot 2.0.4中修复!然后,您可以在服务器端使用WebFlux和Jersey进行测试。

谢谢您的建议,但错误保持不变。我认为日志消息只是意味着Jersey没有在内部找到处理程序方法,就像没有具有匹配模式的处理程序一样。错误意味着框架(即SpringWebFlux测试框架)找不到该方法。这只有在您仍然使用该框架的一部分
WebTestClient
时才会发生。我看不出您的答案(除了明显的Java vs Kotlin)与我的答案有什么不同,除了我让客户端成为类成员(这样您就不会重复创建昂贵的客户端)和我注入端口之外(因为您使用的是Spring boots random port,所以您不能保证它是8080)。除此之外,您的答案完全相同。不要认为这会导致与以前相同的错误。@PaulSamsotha我写了我的答案来解释实际问题,并包括示例(基本上是您的示例)只是为了完整性。
WebTestClient
是一个通用客户端,但它与WebFlux一起提供,与Springs magic的结合是一个问题。这就是我想与未来读者分享的所有内容。创建测试客户端的方式更好,我只是缩短了代码,因为这个细节对于解决这个特定的问题并不重要问题。如果我在阅读了您的示例后删除了WebFlux,问题本来会得到解决,但我不明白发生了什么。通过“universal client”我指的是一个实际的客户端,它可以进行网络调用,我不认为WebTestClient是这样的。它被设计成以编程方式调用实际的处理程序方法,就像MockMvc一样。也许我的回答中的措辞和你的不一样,但我说的是完全一样的。也许你只是误解了。但一切都很好。无论如何,谢谢感谢您的努力!希望其中一个答案能对面临相同问题的人有所帮助。
WebTestClient
执行真正的HTTP请求,顺便说一下:
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")
}
@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)
    }
}