Kết nối bị từ chối khi cố gắng gọi Wiremock Stub

Aug 17 2020

Tôi đang cố gắng tích hợp Cucumber-JVM với WireMock và tôi tiếp tục nhận được

java.net.ConnectException: Connection refused: connect

Tôi đã thử một số hướng dẫn, bao gồm cả Tài liệu chính thức từ dưa chuột.io Và tôi cũng đã thử những hướng dẫn này bên dưới:

Giới thiệu về WireMock từ Baeldung

Nội dung từ StackOverflow

Trang sự cố Wiremock Github

Các phụ thuộc Gradle của tôi:

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'

Ý tưởng cơ bản là Giả lập phản hồi của máy chủ, vì vậy trong tương lai, tôi sẽ có thể tạo một số thử nghiệm tích hợp giữa một số dịch vụ nhỏ. Ý tưởng đến từ một cuốn sách trong khi tôi đang đọc Cuốn sách Dưa chuột cho Java Nếu có những cách tốt hơn để kiểm tra các dịch vụ vi mô, tôi sẵn sàng đón nhận những ý tưởng mới.

Tôi đã có một Lớp kiểm tra với Định nghĩa bước của tôi rằng việc nhận thông tin cổng sẽ tạo thành một tệp thích hợp. Như bên dưới:

@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")));
    }
}

Và tôi cũng đã tạo một kho lưu trữ với một ví dụ có thể chạy được.

Nếu bạn không tìm thấy tệp README, trong khi tìm repo, bạn có thể chạy dự án bằng cách sử dụng:

./gradlew cucumber

hoặc nếu bạn đang sử dụng Windows:

gradle cucumber

Sau khi tôi làm cho nó hoạt động, tôi đã cấu trúc lại mã và để lại ví dụ trên kho lưu trữ mà tôi đã liên kết ở trên, nếu bạn gặp vấn đề tương tự, hãy kiểm tra.

Trả lời

2 M.P.Korstanje Aug 18 2020 at 02:17

Phụ WireMockRulethuộc vào @Rulechú thích đến từ JUnit 4. Nó không có bất kỳ tác dụng nào khi được sử dụng trong Cucumber. Thay vào đó, hãy cân nhắc sử dụng @AutoConfigureWireMocktừ spring-boot-starter-webđể thiết lập 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}
3 ManojRamanan Aug 17 2020 at 14:28

java.net.ConnectException: Kết nối bị từ chối: kết nối này có nghĩa là không có dịch vụ lắng nghe trên cổng, vui lòng thử in cổng mà dịch vụ đang chạy và kiểm tra. Tôi có thể thấy bạn đã kiểm tra xem wiremock có đang chạy hay không, vui lòng kiểm tra cả cổng

Bạn có thể thêm thuộc tính thử nghiệm như thế này. điều đó sẽ ghi đè ứng dụng mặc định.properties

    @TestPropertySource(properties = {
        "application.location=http://localhost:8082/app/api/v1/"

})

vui lòng thay đổi url trong dòng thành

 Header header = new Header("Accept","application/json")
 messageResult = given().header(header).port(8082).get("/message").getBody().asString();

thay vì

  messageResult = given().get("localhost:8082/message").getBody().asString();

Đó là làm việc cho tôi

@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\"}")));
    }
}

Đây là mã làm việc mà bạn đang sử dụng quy tắc mô hình dây và máy chủ mô phỏng dây, chúng tôi không cần sử dụng cả hai vì theo tài liệu bạn có thể sử dụng quy tắc wiremock một mình là đủ, nó sẽ khởi động và dừng máy chủ trước mọi thử nghiệm

xin vui lòng tham khảo http://wiremock.org/docs/getting-started/

Không sử dụng cổng ngẫu nhiên vì trường hợp thử nghiệm này có thể không thành công trong các môi trường khác, hãy sử dụng cổng cố định như bạn đã làm với mã của mình

Bạn có thể sử dụng quy tắc wiremock hoặc cách sử dụng mùa xuân @AutoConfigureWireMock, nó sẽ tự động đưa các phần phụ thuộc vào để mùa xuân sẽ bắt đầu và dừng máy chủ giả thay vì junit.

xin vui lòng tham khảo https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-wiremock cho tài liệu giả dây lò xo

một điều nữa cần lưu ý ở đây @Rule được thực thi trước mùa xuân vì vậy nó không nhận được giá trị cổng vì @Rule thuộc về junit, bạn phải chỉ mã cứng cổng trong chú thích @Rule hoặc bạn có thể sử dụng @AutoConfigureWireMock đó là lý do tôi có mã hóa nó