Wiremock Stub을 호출하려고 할 때 연결이 거부되었습니다.
Cucumber-JVM을 WireMock과 통합하려고하는데 계속해서
java.net.ConnectException: Connection refused: connect
나는 cucumber.io 의 공식 문서 를 포함하여 여러 튜토리얼을 시도했으며 아래에서도 시도했습니다.
Baeldung의 WireMock 소개
StackOverflow의 항목
Wiremock Github 문제 페이지
내 Gradle 종속성 :
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'io.cucumber:cucumber-java:6.2.2'
testImplementation 'io.cucumber:cucumber-junit:6.2.2'
testImplementation 'io.rest-assured:spring-web-test-client:4.3.1'
testCompile "com.github.tomakehurst:wiremock-jre8:2.27.0"
compile group: 'io.cucumber', name: 'cucumber-spring', version: '6.4.0'
기본 아이디어는 서버 응답을 모의하는 것이므로 앞으로 여러 마이크로 서비스 간의 통합 테스트를 만들 수있을 것입니다. 이 아이디어는 제가 The Cucumber for Java Book을 읽는 동안 책에서 나왔습니다. 마이크로 서비스를 테스트하는 더 좋은 방법이 있다면 저는 새로운 아이디어에 열려 있습니다.
포트 정보를 속성 파일에서 얻는 단계 정의가있는 테스트 클래스가 있습니다. 아래와 같이 :
@SpringBootTest
@CucumberContextConfiguration
public class ConnectionWithCucumber {
@Value("${another.server.port}")
private int PORT;
@Rule
private WireMockRule wireMockRule = new WireMockRule(PORT);
private String messageResult;
@Given("I want to read a message")
public void iWantToRead() {
createMessageStub();
}
@When("I send the request")
public void iSendTheRequest() {
messageResult = given().get("localhost:8082/message").getBody().asString();
}
@Then("I should be able to read the word {string}")
public void iShouldBeAbleToReadTheWord(String arg0) {
assertEquals(arg0, messageResult);
}
private void createMessageStub() {
wireMockRule.stubFor(get(urlEqualTo("/message"))
.withHeader("Accept", equalTo("application/json"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("message")));
}
}
또한 실행 가능한 예제 로 저장소 를 만들었습니다 .
README 파일을 찾지 못한 경우 저장소를 찾는 동안 다음을 사용하여 프로젝트를 실행할 수 있습니다.
./gradlew cucumber
또는 Windows를 사용하는 경우 :
gradle cucumber
작업을 마친 후 코드를 리팩토링하고 위에서 링크 한 저장소에 예제를 남겨 두었습니다. 동일한 문제가있는 경우 확인하십시오.
답변
는 WireMockRule
온 따라 @Rule
오이에 사용될 때이 적용되지 않습니다 JUnit을 4에서 온다 주석. 대신 @AutoConfigureWireMock
from spring-boot-starter-web
을 사용하여 wiremock을 설정하는 것이 좋습니다.
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── example
│ └── Application.java
└── test
├── java
│ └── com
│ └── example
│ └── CucumberTest.java
└── resources
├── application.yml
├── com
│ └── example
│ └── hello.feature
└── junit-platform.properties
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>
<groupId>com.example</groupId>
<artifactId>com.example</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<cucumber.version>6.5.0</cucumber.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Hoxton.SR7</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-stub-runner</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>${cucumber.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-junit-platform-engine</artifactId> <version>${cucumber.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
package com.example;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class Application {
@Configuration
@ConfigurationProperties("com.example")
public static class HelloConfiguration {
String helloService;
public String getHelloService() {
return helloService;
}
public void setHelloService(String helloService) {
this.helloService = helloService;
}
}
@RestController
public static class HelloController {
private final RestTemplate helloService;
public HelloController(
RestTemplateBuilder restTemplateBuilder,
HelloConfiguration configuration) {
this.helloService = restTemplateBuilder
.rootUri(configuration.getHelloService())
.build();
}
@RequestMapping("/local")
public String local() {
return "Greetings from Local!";
}
@RequestMapping("/remote")
public String remote() {
return helloService.getForObject("/", String.class);
}
}
}
package com.example;
import com.github.tomakehurst.wiremock.client.WireMock;
import io.cucumber.java.en.Given;
import io.cucumber.junit.platform.engine.Cucumber;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.contract.wiremock.AutoConfigureWireMock;
import org.springframework.test.web.servlet.MockMvc;
import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@Cucumber
@CucumberContextConfiguration
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureWireMock(port = 0)
public class CucumberTest {
@Autowired
private MockMvc mvc;
@Given("the application says hello")
public void getLocalHello() throws Exception {
mvc.perform(get("/local").accept(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Local!")));
}
@Given("the stub says hello")
public void getRemoteHello() throws Exception {
stubFor(WireMock.get("/").willReturn(okJson("Greetings from Stub!")));
mvc.perform(get("/remote").accept(APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string(equalTo("Greetings from Stub!")));
}
}
Feature: Hello world
Scenario: Calling a rest end point
* the application says hello
* the stub says hello
com:
example:
hello-service: http://localhost:${wiremock.server.port}
java.net.ConnectException : 연결이 거부 됨 : 연결은 포트에서 수신하는 서비스가 없음을 의미합니다. 서비스가 실행중인 포트를 인쇄하고 확인하십시오. wiremock이 실행 중인지 여부를 이미 확인했음을 알 수 있습니다. 포트도 확인하십시오.
이와 같이 테스트 속성을 추가 할 수 있습니다. 기본 application.properties를 재정의합니다.
@TestPropertySource(properties = {
"application.location=http://localhost:8082/app/api/v1/"
})
줄의 URL을 다음으로 변경하십시오.
Header header = new Header("Accept","application/json")
messageResult = given().header(header).port(8082).get("/message").getBody().asString();
대신에
messageResult = given().get("localhost:8082/message").getBody().asString();
그것은 나를 위해 일하고있다
@SpringBootTest
@CucumberContextConfiguration
public class ConnectionWithCucumber {
@Value("${another.server.port}") private int PORT; @Rule private WireMockRule wireMockRule = new WireMockRule(8082); private WireMockServer wireMockServer = new WireMockServer(8083); private String messageResult; @Value("${test.word}")
private String word;
@Value("${test.number}")
private String number;
@Test
public void testWord(){
wireMockServer.start();
wireMockRule.start();
wireMockRule.isRunning();
wireMockServer.isRunning();
System.out.println(wireMockRule.port());
assertThat(word).isEqualTo("word");
assertThat(number).isEqualTo("number");
}
@Given("I want to read a message")
public void iWantToRead() {
wireMockServer.start();
wireMockRule.start();
wireMockRule.isRunning();
wireMockServer.isRunning();
System.out.println("wireMockRule port " + wireMockRule.port());
System.out.println("wireMockServer port " + wireMockServer.port());
// Start the stub
createMessageStubServer();
createMessageStub();
wireMockServer.getStubMappings();
wireMockRule.getStubMappings();
}
@When("I send the request")
public void iSendTheRequest() {
System.out.println("iSendTheRequest" + wireMockRule.isRunning());
System.out.println("iSendTheRequest" + wireMockServer.isRunning());
Header header = new Header("Content-Type","application/json");
messageResult = given().port(8082).and().header("Accept","application/json").and()
.get("/message").getBody().asString();
System.out.println(messageResult);
}
@Then("I should be able to read the word {string}")
public void iShouldBeAbleToReadTheWord(String arg0) {
System.out.println(messageResult);
System.out.println("arg0"+arg0);
assertEquals(arg0, messageResult);
}
private void createMessageStub() {
wireMockRule.stubFor(get(urlEqualTo("/message"))
.withHeader("Accept", equalTo("application/json"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("Response")));
}
private void createMessageStubServer() {
wireMockServer.stubFor(get(urlEqualTo("/message"))
.withHeader("Accept", equalTo("application/json"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"message\":\"1\"}")));
}
}
이것은 와이어 모의 규칙과 와이어 모의 서버를 사용하는 작업 코드입니다. 문서에 따라 둘 다 사용할 필요가 없습니다. 모든 테스트 전에 서버를 시작하고 중지하는 데 충분한 wiremock 규칙 만 사용할 수 있습니다.
참조하시기 바랍니다 http://wiremock.org/docs/getting-started/
이 테스트 케이스는 다른 환경에서 실패 할 수 있으므로 임의 포트를 사용하지 마십시오. 코드에서했던 것처럼 고정 포트를 사용합니다.
wiremock 규칙을 사용하거나 @AutoConfigureWireMock을 사용하는 스프링 방식을 사용할 수 있습니다. 이것은 의존성을 자동 주입하므로 스프링이 junit 대신 모의 서버를 시작하고 중지합니다.
참조하시기 바랍니다 https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-wiremock 스프링 와이어 모의 문서 용
여기서 한 가지 더 주목할 점은 @Rule이 스프링 전에 실행되므로 @Rule이 junit에 속해 있기 때문에 포트 값을 얻지 못합니다. @Rule 주석에서 포트를 하드 코딩하거나 @AutoConfigureWireMock을 사용할 수 있습니다. 그것을 하드 코딩