Spring - 如何为soap服务构建一个junit测试

Posted

技术标签:

【中文标题】Spring - 如何为soap服务构建一个junit测试【英文标题】:Spring - How to build a junit test for a soap service 【发布时间】:2020-05-13 02:32:41 【问题描述】:

我正在按照 spring 指南创建一个 hello world 肥皂 ws。以下链接:

https://spring.io/guides/gs/producing-web-service/

我成功地让它工作了。当我运行这个命令行时:

curl --header "content-type: text/xml" -d @src/test/resources/request.xml http://localhost:8080/ws/coutries.wsdl

我收到此回复。

<SOAP-ENV:Header/><SOAP-ENV:Body><ns2:getCountryResponse xmlns:ns2="http://spring.io/guides/gs-producing-web-service"><ns2:country><ns2:name>Spain</ns2:name><ns2:population>46704314</ns2:population><ns2:capital>Madrid</ns2:capital><ns2:currency>EUR</ns2:currency></ns2:country></ns2:getCountryResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

现在我正在尝试为此服务(控制器层)创建一个 junit 测试,但它不起作用。

这是我的单元测试:

@RunWith(SpringRunner.class)
@WebMvcTest(CountryEndpoint.class)
@ContextConfiguration(classes = CountryRepository.class, WebServiceConfig.class)
public class CountryEndpointTest 

    private final String URI = "http://localhost:8080/ws/countries.wsdl";

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void test() throws Exception 


        mockMvc.perform(

                get(URI)
                        .accept(MediaType.TEXT_XML)
                        .contentType(MediaType.TEXT_XML)
                        .content(request)

        )
                .andDo(print())
                .andExpect(status().isOk());
    

    static String request = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
            "                  xmlns:gs=\"http://spring.io/guides/gs-producing-web-service\">\n" +
            "    <soapenv:Header/>\n" +
            "    <soapenv:Body>\n" +
            "        <gs:getCountryRequest>\n" +
            "            <gs:name>Spain</gs:name>\n" +
            "        </gs:getCountryRequest>\n" +
            "    </soapenv:Body>\n" +
            "</soapenv:Envelope>";

这是错误:

MockHttpServletResponse:
           Status = 404
    Error message = null
          Headers = 
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

java.lang.AssertionError: Status 
Expected :200
Actual   :404

我将日志级别更改为调试,我发现了这个:

2020-01-27 18:04:11.880  INFO 32723 --- [           main] c.s.t.e.s.endpoint.CountryEndpointTest   : Started CountryEndpointTest in 1.295 seconds (JVM running for 1.686)
2020-01-27 18:04:11.925 DEBUG 32723 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /ws/countries.wsdl
2020-01-27 18:04:11.929 DEBUG 32723 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/ws/countries.wsdl]
2020-01-27 18:04:11.930 DEBUG 32723 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Matching patterns for request [/ws/countries.wsdl] are [/**]
2020-01-27 18:04:11.930 DEBUG 32723 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : URI Template variables for request [/ws/countries.wsdl] are 
2020-01-27 18:04:11.931 DEBUG 32723 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapping [/ws/countries.wsdl] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@c7a977f]]] and 1 interceptor

我尝试了另一种解决方案(如下),但它也不起作用。

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = WebServiceConfig.class, CountryRepository.class)
public class CountryEndpointTest 

    private final String URI = "http://localhost:8080/ws/countries.wsdl";

    private MockMvc mockMvc;

    @Autowired
    CountryRepository countryRepository;


    @Before
    public void setup() 
        this.mockMvc = standaloneSetup(new CountryEndpoint(countryRepository)).build();
    

【问题讨论】:

【参考方案1】:

春季文档说: https://docs.spring.io/spring-boot/docs/2.1.5.RELEASE/reference/html/boot-features-testing.html

默认情况下,@SpringBootTest 不会启动服务器。

你需要定义

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 

运行服务器。

我尝试使用 mockserver,但无法访问端点(即使使用 WebEnvironment.DEFINED_PORT)

所以我做了如下:

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebTestClient
public class FacturationEndpointTest 

@Autowired
private WebTestClient webClient;

@Test
public void testWSDL() throws Exception 

    this.webClient.get().uri("/test_service/services.wsdl")
            .exchange().expectStatus().isOk();


如果你想像我一样使用 WebTestClient,你需要在 pom.xml 中添加以下依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <scope>test</scope>
</dependency>

【讨论】:

它就像魔术一样工作!!!我必须升级我的 Spring Boot 版本(我在 1.X.X 版中)才能使用 webflux。感谢您的评论和解决方案@bastien【参考方案2】:

请将GET 方法更改为POST

mockMvc.perform(

                postURI) // <-- This line!!!
                        .accept(MediaType.TEXT_XML)
                        .contentType(MediaType.TEXT_XML)
                        .content(request)

【讨论】:

我改变了它,但它似乎并没有解决问题。我有 404 作为状态。【参考方案3】:

如果您使用 spring ws 框架来实现端点,请参阅 spring-ws-test。您将找到一个 MockWebServiceClient 来模拟客户端并测试您的端点。我建议你看看这个例子:https://memorynotfound.com/spring-ws-server-side-integration-testing/

这仅适用于 Spring Web 服务,不适用于 CXF Web 服务。

【讨论】:

感谢 Badreddine 的回复。不幸的是,该示例不适用于我的情况,因为我使用的是较新版本的 spring boot (1.5.6.RELEASE),但该示例使用了已弃用的版本 (mvnrepository.com/artifact/org.springframework.boot/…)。 另一种解决方案可能是 RestAssured 框架,请参阅用法:github.com/rest-assured/rest-assured/wiki/Usage

以上是关于Spring - 如何为soap服务构建一个junit测试的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Spring Boot RESTful Web 服务配置多级身份验证?

在 C# 中,如何为 Praxedo 业务事件附件管理器创建 SOAP 集成?

如何为 Spring Boot JPA 时间戳指定 UTC 时区

如何为 Spring Boot 应用程序的 gradle 构建设置活动配置文件?

如何为 Spring WebFlux 配置 netty 连接超时

如何为 WCF 指定自定义 SoapAction