私はこのパーティーに後半3年間だが、それはので、私はそれが答えとして私の解決策を文書化するに値する、それは他の誰かを手動で扱うの頭痛の種を救うかもしれないのでかかわらず、私に同じ問題を介して動作するためにしばらく時間がかかりましたSOAPペイロードをゼロから作成します。
私は私の統合テスト・スイートのために、この問題を解決しようとする研究のについて合理的なをしました。 CXFカスタム生成サーバ、SOAP-UI、テストコンテキストで実際のクライアントを置き換えるCGLIBの影響を受けたライブラリなど、あらゆる種類のものを試してみました。
のすべての値を処理するために、custom request matchersのWireMockが使用されました。
要点は、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();
}
要求マーシャリング解除
/**
* 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;
}
をマーシャリング
レスポンスが要求ペイロード覗くと要求されたものの動作を見ているため、いくつかのXPathユーティリティました。
すべてのSOAP処理が働いて得るためにfiddliest一部でした。そこからWireMocksを補う独自のAPIを作成するだけです。たとえば、
などです。その結果、良い、希薄なテストになります。
SoapContext context = new SoapContext(...) // URIs, QName, Prefix, ect
context.stubOperation("createUser", CreateUser.class, (u) -> "myUser".equals(u.getUserName()), new CreateUserResponse());
soapClient.createUser("myUser");
https://github.com/skjolber/mockito-soap-cxf – ThomasRS