Wiremock Stub'ı aramaya çalışırken bağlantı reddedildi
Cucumber-JVM'yi WireMock ile entegre etmeye çalışıyorum ve
java.net.ConnectException: Connection refused: connect
Cucumber.io'daki Resmi Belgeler de dahil olmak üzere birkaç öğretici denedim ve ayrıca bunları da denedim:
Baeldung'dan WireMock'a Giriş
StackOverflow'dan öğeler
Wiremock Github Sorunları sayfası
Gradle bağımlılıklarım:
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'
Temel fikir, bir Sunucu Yanıtıyla Alay Etmektir, bu nedenle gelecekte birkaç mikro hizmet arasında bazı entegrasyon testleri oluşturabileceğim. Fikir, The Cucumber for Java Book'u okurken bir kitaptan geldi Mikro hizmetleri test etmenin daha iyi yolları varsa, yeni fikirlere açığım.
Adım Tanımlarımın bulunduğu bir Test Sınıfım var ve bağlantı noktası bilgilerini bir özellik dosyası oluşturuyor. Aşağıdaki gibi:
@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")));
}
}
Ayrıca çalıştırılabilir bir örnek içeren bir depo oluşturdum .
Bir README dosyası bulamazsanız, depoya bakarken projeyi aşağıdakileri kullanarak çalıştırabilirsiniz:
./gradlew cucumber
veya Windows kullanıyorsanız:
gradle cucumber
Çalıştırdıktan sonra, kodu yeniden düzenledim ve yukarıda bağladığım depodaki örneği bıraktım, aynı problemi yaşıyorsanız kontrol edin.
Yanıtlar
WireMockRule
Bağlıdır @Rule
Salatalık kullanıldığında herhangi bir etkisi yoktur JUnit 4. gelmektedir açıklama. Bunun yerine @AutoConfigureWireMock
, spring-boot-starter-web
wiremock'u kurmak için from kullanmayı düşünün.
├── 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: Bağlantı reddedildi: bu bağlantı, bağlantı noktasında dinleyen hizmet olmadığı anlamına gelir, lütfen hizmetin çalıştığı bağlantı noktasını yazdırmayı deneyin ve kontrol edin. Wiremock'un çalışıp çalışmadığını kontrol ettiğinizi görebiliyorum, lütfen portu da kontrol edin
Bunun gibi test özelliği ekleyebilirsiniz. bu, varsayılan application.properties öğesini geçersiz kılar
@TestPropertySource(properties = {
"application.location=http://localhost:8082/app/api/v1/"
})
lütfen satırdaki url'yi şu şekilde değiştirin:
Header header = new Header("Accept","application/json")
messageResult = given().header(header).port(8082).get("/message").getBody().asString();
onun yerine
messageResult = given().get("localhost:8082/message").getBody().asString();
benim için çalışıyor
@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\"}")));
}
}
Bu, kullandığınız tel alay kuralı ve tel alay sunucusunu kullandığınız çalışma kodudur, her ikisini de dokümantasyona göre kullanmanıza gerek yoktur, tek başına wiremock kuralını kullanabilirsiniz, bu yeterlidir, her testten önce sunucuyu başlatır ve durdurur
lütfen bakın http://wiremock.org/docs/getting-started/
Bu test durumları diğer ortamlarda başarısız olabileceğinden rastgele bağlantı noktası kullanmayın, kodunuzda yaptığınız gibi sabit bağlantı noktasını kullanın
Ya wiremock kuralını ya da @AutoConfigureWireMock'u kullanmanın spring yolunu kullanabilirsiniz, bu bağımlılıkları otomatik olarak enjekte eder, böylece spring, junit yerine sahte sunucuyu başlatır ve durdurur.
lütfen bakın https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-wiremock yay teli sahte belgeleri için
Burada dikkat edilmesi gereken bir şey daha var @ Kural ilkbahardan önce yürütülür, bu nedenle @ Kural junit'e ait olduğu için bağlantı noktası değerini almıyor, yalnızca @ Kural açıklamasında bağlantı noktasını sabit kodlamanız gerekir veya @AutoConfigureWireMock'u kullanabilirsiniz. kodlanmış