Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中与SOAP Web服务一起使用WireMock_Java_Web Services_Soap_Mocking_Wiremock - Fatal编程技术网

在Java中与SOAP Web服务一起使用WireMock

在Java中与SOAP Web服务一起使用WireMock,java,web-services,soap,mocking,wiremock,Java,Web Services,Soap,Mocking,Wiremock,我是个新手 到目前为止,我一直在使用SOAPUI模拟响应。我的用例很简单: 只需将soapxml请求发送到不同的端点()并获得固定的XML响应。但是MockWrire必须作为一个独立的服务部署到一个专用的服务器上,该服务器将充当一个中心位置,从那里提供模拟响应 只是想要一些开始的建议。正如我所看到的,WireMock更适合RESTWeb服务。因此,我的疑问是: 1) 我是否需要将其部署到JavaWeb服务器或容器,以充当始终运行独立服务的角色。我读到你可以通过使用 java -jar mockw

我是个新手

到目前为止,我一直在使用SOAPUI模拟响应。我的用例很简单:

只需将soapxml请求发送到不同的端点()并获得固定的XML响应。但是MockWrire必须作为一个独立的服务部署到一个专用的服务器上,该服务器将充当一个中心位置,从那里提供模拟响应

只是想要一些开始的建议。正如我所看到的,WireMock更适合RESTWeb服务。因此,我的疑问是:

1) 我是否需要将其部署到JavaWeb服务器或容器,以充当始终运行独立服务的角色。我读到你可以通过使用

java -jar mockwire.jar --port [port_number]
2) 我需要使用MockWire API吗?我需要为我的用例创建类吗?在我的例子中,请求将通过JUnit测试用例触发以进行模拟

3) 如何实现简单的URL模式匹配?如上所述,我只需要简单的模拟,即在请求发出时获得响应


4) 我的用例有更好/更简单的框架吗?我读过Mockable,但它对3名团队成员和免费层中的演示域有限制。

我是WireMock的创建者

最近,我在一个客户端项目上使用WireMock模拟了一组SOAP接口,因此我可以证明这是可能的。至于它比soapui好还是坏,我想说有一些明确的优点,但有一些折衷。一个主要好处是部署和编程访问/配置相对容易,并且支持HTTPS和低级故障注入等功能。然而,您需要做更多的工作来解析和生成SOAP有效负载——它不会像SOAP UI那样从WSDL生成代码/存根

我的经验是,像soapui这样的工具可以让您更快地启动,但从长远来看,当您的测试套件超出了琐碎的需求时,往往会导致更高的维护成本

依次阐述你的观点: 1) 如果您想让mock在某个服务器上运行,最简单的方法是运行独立的JAR,如您所述。我建议不要尝试将其部署到容器中—此选项只在没有其他选择时才存在

但是,如果您只想运行集成测试或完全自包含的功能测试,我建议使用JUnit规则。我想说,如果a)您正在将其他部署的系统插入其中,或者b)您正在从非JVM语言使用它,那么在专用进程中运行它才是一个好主意

2) 您需要通过以下三种方式之一进行配置:1)Java API、2)HTTP上的JSON或3)JSON文件。3) 可能最接近您对SOAP UI的习惯

3) 有关使用JSON和Java的大量存根示例,请参阅。由于SOAP倾向于绑定到固定端点URL,您可能需要
urlEqualTo(…)
。当我在过去中断SOAP时,我倾向于在整个请求体上进行XML匹配(请参阅)。我建议投资编写一些Java构建器,以生成所需的请求和响应体XML


4) 和都是WireMock的成熟替代品,但它们没有提供任何更明确的SOAP支持。

我参加这次聚会晚了三年多,但是我花了一段时间来解决同一个问题,所以我认为有必要将我的解决方案记录下来作为一个答案,这样就可以避免其他人从头开始手动处理SOAP有效负载的头痛

为了解决我的集成测试套件的这个问题,我做了大量的研究。尝试了各种各样的东西,包括CXF自定义生成的服务器、SOAP-UI、一个受CGLIB影响的库,它在测试上下文中替换了真实的客户机

我最终使用WireMock with来处理所有的
SOAP
-ynes

它的要点是一个类,它处理SOAP请求的解组和SOAP响应的封送,以便为测试只需要JAXB生成的对象而不必关心SOAP细节的作者提供一个方便的包装器

响应编组

/**
 * Accepts a WebService response object (as defined in the WSDL) and marshals
 * to a SOAP envelope String.
 */
public <T> String serializeObject(T object) {
    ByteArrayOutputStream byteArrayOutputStream;
    Class clazz = object.getClass();
    String responseRootTag = StringUtils.uncapitalize(clazz.getSimpleName());
    QName payloadName = new QName("your_namespace_URI", responseRootTag, "namespace_prefix");

    try {
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        Marshaller objectMarshaller = jaxbContext.createMarshaller();

        JAXBElement<T> jaxbElement = new JAXBElement<>(payloadName, clazz, null, object);
        Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
        objectMarshaller.marshal(jaxbElement, document);

        SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
        SOAPBody body = soapMessage.getSOAPPart().getEnvelope().getBody();
        body.addDocument(document);

        byteArrayOutputStream = new ByteArrayOutputStream();
        soapMessage.saveChanges();
        soapMessage.writeTo(byteArrayOutputStream);
    } catch (Exception e) {
        throw new RuntimeException(String.format("Exception trying to serialize [%s] to a SOAP envelope", object), e);
    }

    return byteArrayOutputStream.toString();
}
  • 我以独立方式运行wiremock服务器
  • 我创建了一个mapping.json文件,放在我的模拟项目“mappings”文件夹中

    {“请求”:{
    “url”:“/WebServiceServer/numberconversion”,
    “方法”:“POST”},
    “答复”:{
    “地位”:200,
    “bodyFileName”:“response.xml”,
    “标题”:{
    “服务器”:“Microsoft IIS/8.0”,
    “访问控制允许源”:http://www.dataaccess.com",
    “访问控制允许方法”:“获取、发布”,
    “连接”:“保持活动状态”,
    “Web服务”:“DataFlex 18.1”,
    “访问控制允许标头”:“内容类型”,
    “日期”:“2018年6月26日星期二07:45:47 GMT”,
    “严格的运输安全”:“最大年龄=31536000”,
    “缓存控制”:“专用,最大年龄=0”,
    “访问控制允许凭据”:true,
    “内容长度”:352,
    “内容类型”:“应用程序/soap+xml;字符集=utf-8”
    }}}

  • 我创建了一个响应xml文件,将其放在“\u文件”文件夹中

    
    十二美元
    


  • 请您解释一下,我如何指定“\u文件”和“映射”文件夹使用的相对/绝对路径?我通过maven设置了mockwire依赖项,并创建了一个简单的servlet来执行
    wireMockServer.start()初始化()
    。我猜
    with rootdirectory()
    使用files underdirectory()
    with
    WireMockConfiguration
    应该有效?我通过创建自定义
    文件源
    并将其传递到
    WireMockConfiguration
    解决了这个问题。谢谢。@Tom你在StackOverflow方面不是很多产,但我只是想说WireMock是一个很棒的工具-非常感谢!Tom,你能提供一些例子吗?@RafalEnden我的回答中包含了所有需要工作的例子的代码。太棒了,谢谢分享!我申请将其添加到WireMock。我有个问题。我有肥皂1.2。我已经创建了端点,但它给了我一个错误:一个so
    /**
     * Accepts a WebService request object (as defined in the WSDL) and unmarshals
     * to the supplied type.
     */
    public <T> T deserializeSoapRequest(String soapRequest, Class<T> clazz) {
    
        XMLInputFactory xif = XMLInputFactory.newFactory();
        JAXBElement<T> jb;
        try {
            XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(soapRequest));
    
            // Advance the tag iterator to the tag after Body, eg the start of the SOAP payload object
            do {
                xsr.nextTag();
            } while(!xsr.getLocalName().equals("Body"));
            xsr.nextTag();
    
            JAXBContext jc = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            jb = unmarshaller.unmarshal(xsr, clazz);
            xsr.close();
        } catch (Exception e) {
            throw new RuntimeException(String.format("Unable to deserialize request to type: %s. Request \n %s", clazz, soapRequest), e);
        }
    
        return jb.getValue();
    }
    
    private XPath getXPathFactory() {
    
        Map<String, String> namespaceUris = new HashMap<>();
        namespaceUris.put("xml", XMLConstants.XML_NS_URI);
        namespaceUris.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");       
        // Add additional namespaces to this map        
    
        XPath xpath = XPathFactory.newInstance().newXPath();
    
        xpath.setNamespaceContext(new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
                if (namespaceUris.containsKey(prefix)) {
                    return namespaceUris.get(prefix);
                } else {
                    return XMLConstants.NULL_NS_URI;
                }
            }
    
            public String getPrefix(String uri) {
                throw new UnsupportedOperationException();
            }
    
            public Iterator getPrefixes(String uri) {
                throw new UnsupportedOperationException();
            }
        });
    
        return xpath;
    }
    
    public <T> void stubOperation(String operation, Class<T> clazz, Predicate<T> predicate, Object response) {
        wireMock.stubFor(requestMatching(
                         new SoapObjectMatcher<>(context, clazz, operation, predicate))
                        .willReturn(aResponse()
                        .withHeader("Content-Type", "text/xml")
                        .withBody(serializeObject(response))));
    }
    
    SoapContext context = new SoapContext(...) // URIs, QName, Prefix, ect
    context.stubOperation("createUser", CreateUser.class, (u) -> "myUser".equals(u.getUserName()), new CreateUserResponse());
    
    soapClient.createUser("myUser");