如何在TestMode JAXRSCLIENT中配置Spring Application Context?

时间:2019-11-12 16:28:26

标签: spring-cloud-contract

在应用程序中,控制器使用javax.ws.rs注释进行注释。 据我从文档和示例项目了解,我必须定义一个BaseTestClass,如下所示:

public class BaseTestClass {

    public static WebTarget webTarget;

    private static Server server;

    private static Client client;

    @BeforeClass
    public static void setupTest() throws Exception {
        int port = findAvailableTcpPort(10000);
        URI baseUri = UriBuilder.fromUri("http://localhost").port(port).build();
        // Create Server
        server = new Server(port);
        // Configure ServletContextHandler
        ServletContextHandler context = new ServletContextHandler(
                ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);
        // Create Servlet Container
        ServletHolder jerseyServlet = context
                .addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
        jerseyServlet.setInitOrder(0);

        // Tells the Jersey Servlet which REST service/class to load.        
       jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
                MyController.class.getCanonicalName());
        // Start the server
        server.start();
        ClientConfig clientConfig = new ClientConfig();
        client = ClientBuilder.newClient(clientConfig);
        webTarget = client.target(baseUri);
        try {
            server.start();
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
    }

    @AfterClass
    public static void cleanupTest() {
        if (client != null) {
            client.close();
        }
        if (server != null) {
            try {
                server.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

目前尚不清楚如何以这种方式正确定义我的Spring配置。

我定义的存根:

package contracts

import org.springframework.cloud.contract.spec.Contract

Contract.make {
    name("contract_update")
    request {
        method 'PUT'
        url '/xxx/v1/api'
        headers {
            header 'Content-Type': 'application/vnd.org.springframework.cloud.contract.verifier.twitter-places-analyzer.v1+json'
        }
        body(file("update_request.json"))
    }
    response {
        status OK()
        headers {
            header 'Content-Type': 'application/vnd.org.springframework.cloud.contract.verifier.twitter-places-analyzer.v1+json'
        }
        body(file("update_response.json"))
    }
}

构建时,测试失败,预期200并收到404。我的猜测是,由于应用程序上下文加载失败,因此应用程序实际上未正确加载,因此未找到映射。

为了支持我的猜测,以下是启动服务器时发现的日志:

Nov 12, 2019 6:27:36 PM org.glassfish.jersey.server.spring.SpringComponentProvider initialize
SEVERE: Spring context lookup failed, skipping spring component provider initialization.

1 个答案:

答案 0 :(得分:0)

请检查新添加的带有Spring示例(https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/master/producer_jaxrs_spring)的Spring Cloud Contract JaxRS。为了方便起见,我在这里复制其内容

配置

@SpringBootApplication
public class ProducerWithJaxRsApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProducerWithJaxRsApplication.class, args);
    }

    @Bean
    PersonCheckingService personCheckingService() {
        return argument -> argument.getAge() >= 20;
    }
}

@Component
class JerseyConfig extends ResourceConfig {
    JerseyConfig() {
        register(FraudDetectionController.class);
    }
}

控制器(PersonCheckingService是一种方法的接口)。

package com.example.beerapiproducerjaxrs;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import com.example.beerapiproducerjaxrs.model.FraudCheck;
import com.example.beerapiproducerjaxrs.model.FraudCheckResult;

import org.springframework.web.bind.annotation.RestController;

import static com.example.beerapiproducerjaxrs.model.FraudCheckStatus.NOT_OK;
import static com.example.beerapiproducerjaxrs.model.FraudCheckStatus.OK;

@RestController
@Path("/")
public class FraudDetectionController {

    private final PersonCheckingService service;

    public FraudDetectionController(PersonCheckingService service) {
        this.service = service;
    }

    @POST
    @Path("/check")
    @Produces("application/json;charset=utf-8")
    @Consumes("application/json;charset=utf-8")
    public FraudCheckResult fraudCheck(FraudCheck fraudCheck) {
        if (oldEnough(fraudCheck)) {
            return new FraudCheckResult(OK);
        }
        return new FraudCheckResult(NOT_OK);
    }

    private boolean oldEnough(FraudCheck fraudCheck) {
        return service.shouldGetBeer(fraudCheck);
    }

}

测试的基类

package com.example;

import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;

import com.example.beerapiproducerjaxrs.ProducerWithJaxRsApplication;
import org.junit.Before;
import org.junit.runner.RunWith;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ProducerWithJaxRsApplication.class},
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public abstract class BeerRestBase {

    @LocalServerPort int port;

    public WebTarget webTarget;

    @Before
    public void setup() {
        this.webTarget = ClientBuilder.newClient().target("http://localhost:" + this.port + "/");
    }
}

插件设置(Gradle)

contracts {
    packageWithBaseClasses = 'com.example'
    testMode = "JAXRSCLIENT"
}

还有插件设置(Maven)

        <plugin>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-contract-maven-plugin</artifactId>
            <version>${spring-cloud-contract.version}</version>
            <extensions>true</extensions>
            <configuration>
                <packageWithBaseClasses>com.example</packageWithBaseClasses>
                <testMode>JAXRSCLIENT</testMode>
            </configuration>
        </plugin>