Provider Contract Testing with Stubs in Artifactory for a non-Spring Application
在这个页面里,你将学习如何对非 Spring 应用程序和已上传到 Artifactory 的存根执行提供者合同测试。
In this page you will learn how to do provider contract testing with a non-Spring application and stubs uploaded to Artifactory.
The Flow
您可以阅读 Developing Your First Spring Cloud Contract-based Application 以查看在 Nexus 或 Artifactory 中使用存根进行提供者合同测试的流程。
You can read Developing Your First Spring Cloud Contract-based Application to see the flow for provider contract testing with stubs in Nexus or Artifactory.
Setting up the Consumer
对于消费者端,你可以使用 JUnit 规则。通过这种方式,你不需要启动 Spring 上下文。以下列表展示了该规则(在 JUnit4 和 JUnit 5 中);
For the consumer side, you can use a JUnit rule. That way, you need not start a Spring context. The following listing shows such a rule (in JUnit4 and JUnit 5);
- ===JUnit 4 Rule
=== JUnit 4 Rule::
+
@Rule
public StubRunnerRule rule = new StubRunnerRule()
.downloadStub("com.example","artifact-id", "0.0.1")
.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
.stubsMode(StubRunnerProperties.StubsMode.REMOTE);
- JUnit 5 Extension
-
@RegisterExtension public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() .downloadStub("com.example","artifact-id", "0.0.1") .repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git") .stubsMode(StubRunnerProperties.StubsMode.REMOTE);
===
Setting up the Producer
默认情况下,Spring Cloud Contract 插件为已生成的测试使用 Rest Assured 的 MockMvc
设置。由于非 Spring 应用程序不使用 MockMvc
,你可以将 testMode
更改为 EXPLICIT
,以便向绑定到特定端口的应用程序发送真实请求。
By default, the Spring Cloud Contract Plugin uses Rest Assured’s MockMvc
setup for the
generated tests. Since non-Spring applications do not use MockMvc
, you can change the
testMode
to EXPLICIT
to send a real request to an application bound at a specific port.
在此示例中,我们使用名为 Javalin 的框架来启动非 Spring HTTP 服务器。
In this example, we use a framework called Javalin to start a non-Spring HTTP server.
假设我们拥有以下应用程序:
Assume that we have the following application:
package com.example.demo;
import io.javalin.Javalin;
public class DemoApplication {
public static void main(String[] args) {
new DemoApplication().run(7000);
}
public Javalin start(int port) {
return Javalin.create().start(port);
}
public Javalin registerGet(Javalin app) {
return app.get("/", ctx -> ctx.result("Hello World"));
}
public Javalin run(int port) {
return registerGet(start(port));
}
}
鉴于该应用程序,我们可以设置插件使用 EXPLICIT
模式(即,向真实端口发送请求),如下所示:
Given that application, we can set up the plugin to use the EXPLICIT
mode (that is, to
send out requests to a real port), as follows:
- ===Maven
=== Maven::
+
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<baseClassForTests>com.example.demo.BaseClass</baseClassForTests>
<!-- This will setup the EXPLICIT mode for the tests -->
<testMode>EXPLICIT</testMode>
</configuration>
</plugin>
- Gradle
-
contracts { // This will setup the EXPLICIT mode for the tests testMode = "EXPLICIT" baseClassForTests = "com.example.demo.BaseClass" }
===
基本类可能如下所示:
The base class might resemble the following:
import io.javalin.Javalin;
import io.restassured.RestAssured;
import org.junit.After;
import org.junit.Before;
import org.springframework.cloud.test.TestSocketUtils;
public class BaseClass {
Javalin app;
@Before
public void setup() {
// pick a random port
int port = TestSocketUtils.findAvailableTcpPort();
// start the application at a random port
this.app = start(port);
// tell Rest Assured where the started application is
RestAssured.baseURI = "http://localhost:" + port;
}
@After
public void close() {
// stop the server after each test
this.app.stop();
}
private Javalin start(int port) {
// reuse the production logic to start a server
return new DemoApplication().run(port);
}
}
使用此设置:
With such a setup:
-
We have set up the Spring Cloud Contract plugin to use the
EXPLICIT
mode to send real requests instead of mocked ones. -
We have defined a base class that:
-
Starts the HTTP server on a random port for each test.
-
Sets Rest Assured to send requests to that port.
-
Closes the HTTP server after each test.
-