การเชื่อมต่อถูกปฏิเสธเมื่อพยายามโทรหา Wiremock Stub

Aug 17 2020

ฉันพยายามรวม Cucumber-JVM เข้ากับ WireMock และได้รับเรื่อย ๆ

java.net.ConnectException: Connection refused: connect

ฉันได้ลองใช้แบบฝึกหัดหลายบทรวมถึงเอกสารอย่างเป็นทางการจาก cucumber.io และลองทำสิ่งเหล่านี้ด้านล่าง:

ข้อมูลเบื้องต้นเกี่ยวกับ WireMock จาก Baeldung

Stuff จาก 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 ในขณะที่ค้นหา repo คุณสามารถเรียกใช้โครงการโดยใช้:

./gradlew cucumber

หรือถ้าคุณใช้ Windows:

gradle cucumber

หลังจากที่ฉันใช้งานได้ฉันได้ปรับโครงสร้างโค้ดใหม่และทิ้งตัวอย่างไว้ในพื้นที่เก็บข้อมูลที่ฉันเชื่อมโยงไว้ด้านบนหากคุณมีปัญหาเดียวกันให้ตรวจสอบ

คำตอบ

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

WireMockRuleขึ้นอยู่กับ@Ruleคำอธิบายประกอบซึ่งมาจาก JUnit 4 มันไม่ได้มีผลกระทบใด ๆ เมื่อใช้ในแตงกวา ให้พิจารณาใช้@AutoConfigureWireMockfrom spring-boot-starter-webto setup 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: การเชื่อมต่อถูกปฏิเสธ: เชื่อมต่อซึ่งหมายความว่าไม่มีบริการฟังบนพอร์ตโปรดลองพิมพ์พอร์ตที่บริการกำลังทำงานอยู่และตรวจสอบ ฉันเห็นว่าคุณได้ตรวจสอบแล้วว่า Wiremock กำลังทำงานอยู่หรือไม่โปรดตรวจสอบพอร์ตด้วย

คุณสามารถเพิ่มคุณสมบัติการทดสอบเช่นนี้ ซึ่งจะแทนที่ค่า default 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 มันจะฉีดการพึ่งพาอัตโนมัติดังนั้นฤดูใบไม้ผลิจะเริ่มต้นและหยุดเซิร์ฟเวอร์จำลองแทนจูนิท

โปรดอ้างอิง https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-wiremock สำหรับเอกสารจำลองลวดสปริง

อีกสิ่งหนึ่งที่ควรทราบที่นี่ @Rule ถูกดำเนินการก่อนฤดูใบไม้ผลิดังนั้นจึงไม่ได้รับค่าพอร์ตเนื่องจาก @Rule เป็นของ junit คุณต้องฮาร์ดโค้ดเฉพาะพอร์ตในคำอธิบายประกอบ @Rule หรือคุณสามารถใช้ @AutoConfigureWireMock นั่นคือเหตุผลที่ฉันมี ฮาร์ดโค้ดมัน