2016-03-13 74 views
8

私は全く新しいWireMockです。JavaでSOAP WebサービスでWireMockを使用する

これまで、SOAPUIを使用して模擬応答を使用してきました。

さまざまなエンドポイント(http://localhost:9001/endpoint1)にSOAP XMLリクエストを送信し、XML応答を返すだけです。しかし、MockWrireは、モックレスポンスが提供される中心の場所で動作する専用サーバーにスタンドアロンサービスとして展開する必要があります。

ちょっとした提案がありました。わかるように、WireMockはREST Webサービスに適しています。だから私の疑問は:

1)私はそれをJava Webサーバーまたはコンテナに展開して、常にスタンドアロンサービスを実行する必要がありますか。

java -jar mockwire.jar --port [port_number] 

2)私はMockWire APIを使用する必要がありますか?私はユースケースのためにクラスを作る必要がありますか?私の場合、リクエストはJUnitのテストケースを介して行われます。

3)単純なURLパターンのマッチングはどのように達成できますか?上記のように、単純な模擬、つまりリクエストがあったときに応答を得るだ​​けですhttp://localhost:9001/endpoint1

4)私のユースケースのためのより良い/より簡単なフレームワークはありますか?私はMockableについて読んだが、それは自由な層の3人のチームメンバーとデモドメインに制限がある。

+0

https://github.com/skjolber/mockito-soap-cxf – ThomasRS

答えて

18

私はWireMockの作成者です。

私はWireMockを使用して、クライアント・プロジェクトのSOAPインタフェースの集合をまもなく模擬していますので、可能であることを証明できます。 SOAP UIより優れているのか悪いのかについては、いくつか明確な長所がありますが、いくつかのトレードオフがあります。大きなメリットは、デプロイメントとプログラムによるアクセス/設定が比較的簡単で、HTTPSや低レベルのフォルトインジェクションなどをサポートすることです。しかし、SOAPペイロードを解析して生成するにはもう少し作業を行う必要があります。SOAP UIのようにWSDLからコード/スタブを生成することはありません。

私の経験では、SOAP UIのようなツールを使用する方が速く始めることができますが、テストスイートが些細なことよりも大きくなった場合、長期的には保守コストが高くなる傾向があります。

ポイントに順番に対処するには 1)サーバー上でモックを実行する場合は、これを行う最も簡単な方法は、前述したようにスタンドアロンJARを実行することです。コンテナに展開しようとするのではなく、このオプションは実際には存在しない場合にのみ存在します。

ただし、統合テストや完全に自己完結型の機能テストを実行したい場合は、JUnitルールを使用することをお勧めします。 a)他のデプロイされたシステムをプラグインしている場合、またはb)JVM以外の言語から使用している場合は、専用プロセスで実行することをお勧めします。

2)1)Java API、2)JSON over HTTP、または3)JSONファイルのいずれかで設定する必要があります。 3)はおそらくあなたがSOAP UIで慣れ親しんだものに最も近いでしょう。

3)JSONとJavaの両方を使用する多くのスタブの例については、http://wiremock.org/stubbing.htmlを参照してください。 SOAPは固定エンドポイントURLにバインドする傾向があるため、おそらくurlEqualTo(...)が必要です。過去にSOAPをスタブしたところでは、リクエスト本体全体でXMLの一致が見られました(http://wiremock.org/stubbing.html#xml-body-matching参照)。私は、あなたが必要とするリクエストとレスポンスの本体XMLを生成するために、いくつかのJavaビルダーを書くことに投資することをお勧めします。

4)Mock ServerおよびBetamaxはどちらもWireMockの代替品ですが、AFAIKでは明示的なSOAPサポートを提供していません。

+0

あなたはどのように私は「__files」と「マッピング」フォルダに使用する相対/絶対パスを指定することができ、説明していただけますか? 私はMavenを経由mockwire依存関係を設定すると 'wireMockServer.startを()を実行するための簡単なサーブレットを作成しました;'サーブレットの 'のinit()'。 'WireMockConfiguration'を使って' withRootDirectory() 'または' usingFilesUnderDirectory() 'を推測していますか? – Anurag

+0

カスタムFileSourceを作成し、それを 'WireMockConfiguration'に渡すことで問題を解決しました。ありがとう。 – Anurag

+1

@TomあなたはStackOverflowの上であまりにも多作ではありませんが、私はちょうどWireMockキットの素晴らしい作品であると言うしたかった - おかげでたくさん! – markdsievers

8

私はこのパーティーに後半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"); 
+0

恐ろしい、共有のための感謝を!これをWireMockに追加するため、https://github.com/tomakehurst/wiremock/issues/759を提出しました。 – mrts

関連する問題