Sambungan ditolak saat mencoba menelepon Wiremock Stub
Saya mencoba mengintegrasikan Cucumber-JVM dengan WireMock dan saya terus mendapatkannya
java.net.ConnectException: Connection refused: connect
Saya sudah mencoba beberapa tutorial, termasuk Dokumen Resmi dari cucumber.io Dan juga mencobanya di bawah ini:
Pengantar WireMock dari Baeldung
Item dari StackOverflow
Halaman Masalah Wiremock Github
Dependensi Gradle saya:
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'
Ide dasarnya adalah untuk Meniru Respons Server, jadi di masa mendatang saya akan dapat membuat beberapa pengujian integrasi antara beberapa layanan mikro. Ide tersebut datang dari sebuah buku saat saya membaca The Cucumber for Java Book. Jika ada cara yang lebih baik untuk menguji layanan mikro, saya terbuka untuk ide-ide baru.
Saya memiliki Kelas Tes dengan Definisi Langkah saya yang mendapatkan info port dari file properti. Seperti dibawah ini:
@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")));
}
}
Dan saya juga telah membuat repositori dengan contoh yang dapat dijalankan.
Jika Anda tidak menemukan file README, saat mencari repo Anda dapat menjalankan proyek dengan menggunakan:
./gradlew cucumber
atau jika Anda menggunakan Windows:
gradle cucumber
Setelah saya membuatnya berfungsi, saya memperbarui kode dan meninggalkan contoh di repositori yang saya tautkan di atas, jika Anda memiliki masalah yang sama, periksa.
Jawaban
The WireMockRule
tergantung pada @Rule
penjelasan yang berasal dari JUnit 4. Ia tidak memiliki efek apapun bila digunakan dalam Cucumber. Sebagai gantinya pertimbangkan untuk menggunakan @AutoConfigureWireMock
from spring-boot-starter-web
untuk mengatur 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: Sambungan ditolak: sambungkan ini berarti tidak ada layanan yang mendengarkan di porta, coba cetak port tempat layanan berjalan dan periksa. Saya dapat melihat Anda telah memeriksa apakah wiremock sedang berjalan atau tidak, harap periksa juga portnya
Anda dapat menambahkan properti uji seperti ini. yang akan menimpa application.properties default
@TestPropertySource(properties = {
"application.location=http://localhost:8082/app/api/v1/"
})
harap ubah url di baris menjadi
Header header = new Header("Accept","application/json")
messageResult = given().header(header).port(8082).get("/message").getBody().asString();
dari pada
messageResult = given().get("localhost:8082/message").getBody().asString();
itu bekerja untuk saya
@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\"}")));
}
}
Ini adalah kode kerja Anda menggunakan aturan tiruan kawat dan server tiruan kawat kami tidak perlu menggunakan keduanya sesuai dokumen Anda dapat menggunakan aturan wiremock saja yang cukup itu akan memulai dan menghentikan server sebelum setiap pengujian
silakan lihat http://wiremock.org/docs/getting-started/
Jangan gunakan port acak karena kasus pengujian ini mungkin gagal di lingkungan lain, gunakan port tetap seperti yang Anda lakukan dengan kode Anda
Anda dapat menggunakan aturan wiremock atau cara pegas menggunakan @AutoConfigureWireMock itu akan otomatis menyuntikkan dependecies sehingga spring akan memulai dan menghentikan server tiruan alih-alih junit.
silakan lihat https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-wiremock untuk dokumen tiruan kawat pegas
satu hal lagi yang perlu diperhatikan di sini @Rule dijalankan sebelum musim semi sehingga tidak mendapatkan nilai port karena @Rule milik junit Anda hanya perlu kode keras port di anotasi @Rule atau Anda dapat menggunakan @AutoConfigureWireMock itulah alasan saya memilikinya hardcode itu