使用 Stub Runner 引导应用程序
Spring Cloud Contract Stub Runner Boot 是一个 Spring Boot 应用程序,它将 REST 端点公开给 触发消息标签并访问 WireMock 服务器。
Stub Runner 引导安全性
Stub Runner Boot 应用程序在设计上并不安全 - 保护它需要为所有应用程序添加安全性 stubs 的 S 文件,即使他们实际上并不需要它。由于这是一个测试实用程序,因此该服务器不打算在生产环境中使用。
预计只有受信任的客户端才能访问 Stub Runner Boot 服务器。你不应该 在不受信任的位置以 Fat Jar 或 Docker Image 的形式运行此应用程序。 |
Stub Runner 服务器
要使用 Stub Runner Server,请添加以下依赖项:
compile "org.springframework.cloud:spring-cloud-starter-stub-runner"
然后用 来注释一个类,构建一个胖 jar,它就可以工作了。@EnableStubRunnerServer
有关属性,请参阅 Stub Runner Spring 部分。
Stub Runner 服务器 Fat Jar
您可以从 Maven 下载独立的 JAR(例如,对于版本 2.0.1.RELEASE) 通过运行以下命令:
$ wget -O stub-runner.jar 'https://search.maven.org/remotecontent?filepath=org/springframework/cloud/spring-cloud-contract-stub-runner-boot/2.0.1.RELEASE/spring-cloud-contract-stub-runner-boot-2.0.1.RELEASE.jar'
$ java -jar stub-runner.jar --stubrunner.ids=... --stubrunner.repositoryRoot=...
Spring Cloud CLI
从 Spring Cloud CLI 项目的版本开始,您可以通过运行 来启动 Stub Runner Boot。1.4.0.RELEASE
spring cloud stubrunner
要传递配置,可以在当前工作目录下创建一个文件
在名为 的子目录中,或在 中。该文件可能类似于以下内容
运行本地安装的存根的示例:stubrunner.yml
config
~/.spring-cloud
stubrunner:
stubsMode: LOCAL
ids:
- com.example:beer-api-producer:+:9876
然后,您可以从终端窗口调用以启动
Stub Runner 服务器。可在 port 获得。spring cloud stubrunner
8750
端点
例
以下示例显示了 Stub Runner Boot 的典型用法:
@SpringBootTest(classes = StubRunnerBoot, properties = "spring.cloud.zookeeper.enabled=false")
@ActiveProfiles("test")
class StubRunnerBootSpec {
@Autowired
StubRunning stubRunning
@BeforeEach
void setup() {
RestAssuredMockMvc.standaloneSetup(new HttpStubsController(stubRunning),
new TriggerController(stubRunning))
}
@Test
void 'should return a list of running stub servers in "full ivy port" notation'() {
when:
String response = RestAssuredMockMvc.get('/stubs').body.asString()
then:
def root = new JsonSlurper().parseText(response)
assert root.'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs' instanceof Integer
}
@Test
void 'should return a port on which a #stubId stub is running'() {
given:
def stubIds = ['org.springframework.cloud.contract.verifier.stubs:bootService:+:stubs',
'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs',
'org.springframework.cloud.contract.verifier.stubs:bootService:+',
'org.springframework.cloud.contract.verifier.stubs:bootService',
'bootService']
stubIds.each {
when:
def response = RestAssuredMockMvc.get("/stubs/${it}")
then:
assert response.statusCode == 200
assert Integer.valueOf(response.body.asString()) > 0
}
}
@Test
void 'should return 404 when missing stub was called'() {
when:
def response = RestAssuredMockMvc.get("/stubs/a:b:c:d")
then:
assert response.statusCode == 404
}
@Test
void 'should return a list of messaging labels that can be triggered when version and classifier are passed'() {
when:
String response = RestAssuredMockMvc.get('/triggers').body.asString()
then:
def root = new JsonSlurper().parseText(response)
assert root.'org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs'?.containsAll(["return_book_1"])
}
@Test
void 'should trigger a messaging label'() {
given:
StubRunning stubRunning = Mockito.mock(StubRunning)
RestAssuredMockMvc.standaloneSetup(new HttpStubsController(stubRunning), new TriggerController(stubRunning))
when:
def response = RestAssuredMockMvc.post("/triggers/delete_book")
then:
response.statusCode == 200
and:
Mockito.verify(stubRunning).trigger('delete_book')
}
@Test
void 'should trigger a messaging label for a stub with #stubId ivy notation'() {
given:
StubRunning stubRunning = Mockito.mock(StubRunning)
RestAssuredMockMvc.standaloneSetup(new HttpStubsController(stubRunning), new TriggerController(stubRunning))
and:
def stubIds = ['org.springframework.cloud.contract.verifier.stubs:bootService:stubs', 'org.springframework.cloud.contract.verifier.stubs:bootService', 'bootService']
stubIds.each {
when:
def response = RestAssuredMockMvc.post("/triggers/$it/delete_book")
then:
assert response.statusCode == 200
and:
Mockito.verify(stubRunning).trigger(it, 'delete_book')
}
}
@Test
void 'should throw exception when trigger is missing'() {
when:
BDDAssertions.thenThrownBy(() -> RestAssuredMockMvc.post("/triggers/missing_label"))
.hasMessageContaining("Exception occurred while trying to return [missing_label] label.")
.hasMessageContaining("Available labels are")
.hasMessageContaining("org.springframework.cloud.contract.verifier.stubs:loanIssuance:0.0.1-SNAPSHOT:stubs=[]")
.hasMessageContaining("org.springframework.cloud.contract.verifier.stubs:bootService:0.0.1-SNAPSHOT:stubs=")
}
}
具有服务发现的 Stub Runner 引导
使用 Stub Runner Boot 的一种方法是将其用作 “冒烟测试” 的存根源。那是什么意思? 假设您不想为了 Order Order 将 50 个微服务部署到测试环境中 以查看您的应用程序是否正常工作。您已经在构建过程中运行了一套测试。 但您还希望确保应用程序的打包有效。您可以 将应用程序部署到环境,启动它,然后对其运行几个测试以查看 它有效。我们可以将这些测试称为 “冒烟测试”,因为它们的目的是只检查少数几个 的测试场景。
这种方法的问题在于,如果您使用微服务,您很可能还会 使用服务发现工具。Stub Runner Boot 允许您通过启动 必需的存根,并在服务发现工具中注册它们。
现在假设我们要启动此应用程序,以便自动注册存根。
我们可以通过使用 运行应用程序来实现这一点,其中 .java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar
${SYSTEM_PROPS}
这样,您部署的应用程序可以通过 service 向已启动的 WireMock 服务器发送请求
发现。点 1 到 3 很可能默认在 中设置,因为它们不是
可能会改变。这样,您可以只提供启动时要下载的存根列表
Stub Runner 靴子。application.yml