【问题标题】:Spring Boot: Mocking SOAP Web ServiceSpring Boot:模拟 SOAP Web 服务
【发布时间】:2018-06-21 12:35:26
【问题描述】:

我想知道在 Spring Boot 中模拟 SOAP Web 服务的最佳实践是为了运行集成测试。我在 spring 网站上只能找到https://spring.io/guides/gs/consuming-web-service/。我们是否必须为像模拟依赖项这样简单的事情创建一个模式/wsdl?

要模拟一个 REST 服务,我们所要做的就是将 @RestController 注释添加到我们的模拟服务中以使其启动。我一直在寻找一种轻量级的解决方案。

注意:我目前正在使用 REST Assured 进行集成测试。

谢谢!

【问题讨论】:

    标签: java spring spring-boot soap integration-testing


    【解决方案1】:

    我使用 WireMock 模拟了一个外部 SOAP 服务器依赖项。

    测试类本身使用@SpringBootTest 注释来确保我有与真实环境相似的上下文。

    private WireMockServer wireMockServer = new WireMockServer(wireMockConfig().port(8089));
    
    @Autowired
    SoapClient soapClient;
    
    @Test
    @DisplayName("Retrieve SOAP message")
    void retrieveMessage() {
        wireMockServer.start();
        WireMock.configureFor("localhost", 8089);
        WireMock.reset();
        stubFor(post(urlEqualTo("/ECPEndpointService"))
                .willReturn(
                        aResponse()
                                .withStatus(200)
                                .withHeader("Content-Type",
                                        "Multipart/Related; boundary=\"----=_Part_112_400566523.1602581633780\"; type=\"application/xop+xml\"; start-info=\"application/soap+xml\"")
                                .withBodyFile("RawMessage.xml")
                )
        );
        soapClient.retrieveActivations();
        wireMockServer.stop();
    }
    

    RawMessage.xml 的内容是消息响应。就我而言,这是一条多部分消息(简化):

    ------=_Part_112_400566523.1602581633780
    Content-Type: application/xop+xml; charset=utf-8; type="application/soap+xml"
    
    <env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
        <env:Header/>
        <env:Body>
            <ns5:ReceiveMessageResponse xmlns:ns3="http://mades.entsoe.eu/" xmlns:ns4="http://mades.entsoe.eu/2/" xmlns:ns5="http://ecp.entso-e.eu/" xmlns:ns6="http://ecp.entsoe.eu/endpoint">
            <receivedMessage>
                ...
            </receivedMessage>
            <remainingMessagesCount>0</remainingMessagesCount>
            </ns5:ReceiveMessageResponse>
        </env:Body>
    </env:Envelope>
    ------=_Part_112_400566523.1602581633780
    Content-Type: application/octet-stream
    Content-ID: <7a2f354f-dc52-406b-a4b1-9d89aa29cb2d@null>
    Content-Transfer-Encoding: binary
    
    <?xml version="1.0" encoding="UTF-8"?>
    <edx:Message
        xmlns:edx="http://edx.entsoe.eu/internal/messaging/message"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <edxMetadata>
            ...
        </edxMetadata>
        <content v="PEFjdGl2YXRpb25"/>
    
    </edx:Message>
    ------=_Part_112_400566523.1602581633780--
    

    这个设置让我尽可能模拟真实的通话。

    【讨论】:

      【解决方案2】:

      试试这个模板:

      import org.junit.*;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
      import org.springframework.xml.transform.StringSource;
      import org.springframework.ws.test.client.MockWebServiceServer;
      import static org.springframework.ws.test.client.RequestMatchers.*;
      import static org.springframework.ws.test.client.ResponseCreators.*;
      
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration("applicationContext.xml")
      public class MyWebServiceClientIntegrationTest {
      
          // MyWebServiceClient extends WebServiceGatewaySupport, and is configured in applicationContext.xml
          @Autowired
          private MyWebServiceClient client;
      
          private MockWebServiceServer mockServer;
      
          @Before
          public void createServer() throws Exception {
              mockServer = MockWebServiceServer.createServer(client);
          }
       
          @Test
          public void getCustomerCount() throws Exception {
              Source expectedRequestPayload = new StringSource("some expected xml");
              Source responsePayload = new StringSource("some payload xml");
      
              mockServer.expect(payload(expectedRequestPayload)).andRespond(withPayload(responsePayload));
      
              // client.getCustomerCount() uses the WebServiceTemplate
              int customerCount = client.getCustomerCount();
              assertEquals(10, response.getCustomerCount());
      
              mockServer.verify();
          }
      }
      
      

      【讨论】:

      • 我试过这个并得到一个 SaxException : content not allowed in trailing section。
      【解决方案3】:

      最简单的方法是模拟负责与 Soap Web 服务集成的 bean。

      例如,如果您有一个 SoapWebService 使用 Soap 与另一个 Web 服务进行通信,您可以在您的测试中使用 @MockBean 注释并模拟返回。示例:

      @SpringBootTest
      @WebAppConfiguration
      @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
      @RunWith(SpringRunner.class)
      @FixMethodOrder(MethodSorters.NAME_ASCENDING)
      public class YourControllerIT {
      
          @MockBean
          private SoapWebService soapWebService ;
      
          @Before
          public void setup() {
              when(soapWebService.soapCall(
                      any(), anyLong())).thenReturn("mockedInformation");
          }
      
          @Test
          public void addPerson() {
               MvcResult mvcResult = mockMvc.perform(post("/api/persons")
                      .accept("application/json")
                      .header("Content-Type", "application/json")
                      .content(jsonContent))
                      .andExpect(status().isCreated())
                      .andReturn();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-25
        • 1970-01-01
        • 2018-10-25
        • 1970-01-01
        相关资源
        最近更新 更多