如何为Spring的WebServiceTemplate创建一个模拟对象?

Kev*_*vin 7 java spring-ws mocking

我有一个调用现有Web服务的类.我的类正确处理有效的结果以及Web服务生成的错误字符串.对Web服务的基本调用看起来像这样(尽管这是简化的).

public String callWebService(final String inputXml)
{
  String result = null;

  try
  {
    StreamSource input = new StreamSource(new StringReader(inputXml));
    StringWriter output = new StringWriter();

    _webServiceTemplate.sendSourceAndReceiveToResult(_serviceUri, input, new StreamResult(output));

    result = output.toString();
  }
  catch (SoapFaultClientException ex)
  {
    result = ex.getFaultStringOrReason();
  }

  return result;
}
Run Code Online (Sandbox Code Playgroud)

现在我需要创建一些测试所有成功和失败条件的单元测试.它无法调用实际的Web服务,所以我希望有一些模拟对象可用于Spring-WS的客户端.有没有人知道可用于WebServiceTemplate或任何相关类的模拟对象?我是否应该尝试编写自己的类并修改我的类以使用WebServiceOperations接口与WebServiceTemplate?

Kev*_*vin 7

迈克尔的答案非常接近,但这是有效的例子.

我已经使用Mockito进行单元测试了,所以我对图书馆很熟悉.然而,与我之前对Mockito的经历不同,简单地模拟返回结果并没有帮助.我需要做两件事来测试所有用例:

  1. 修改存储在StreamResult中的值.
  2. 抛出SoapFaultClientException.

首先,我需要意识到我不能用Mockito模拟WebServiceTemplate,因为它是一个具体的类(如果这是必不可少的,你需要使用EasyMock).幸运的是,对Web服务的调用sendSourceAndReceiveToResult是WebServiceOperations接口的一部分.这需要更改我的代码以期望WebServiceOperations与WebServiceTemplate.

以下代码支持在StreamResult参数中返回结果的第一个用例:

private WebServiceOperations getMockWebServiceOperations(final String resultXml)
{
  WebServiceOperations mockObj = Mockito.mock(WebServiceOperations.class);

  doAnswer(new Answer()
  {
    public Object answer(InvocationOnMock invocation)
    {
      try
      {
        Object[] args = invocation.getArguments();
        StreamResult result = (StreamResult)args[2];
        Writer output = result.getWriter();
        output.write(resultXml);
      }
      catch (IOException e)
      {
        e.printStackTrace();
      }

      return null;
    }
  }).when(mockObj).sendSourceAndReceiveToResult(anyString(), any(StreamSource.class), any(StreamResult.class));

  return mockObj;
}
Run Code Online (Sandbox Code Playgroud)

对第二个用例的支持是类似的,但需要抛出异常.以下代码创建一个包含faultString的SoapFaultClientException.faultCode由我正在测试的代码使用,用于处理Web服务请求:

private WebServiceOperations getMockWebServiceOperations(final String faultString)
{
  WebServiceOperations mockObj = Mockito.mock(WebServiceOperations.class);

  SoapFault soapFault = Mockito.mock(SoapFault.class);
  when(soapFault.getFaultStringOrReason()).thenReturn(faultString);

  SoapBody soapBody = Mockito.mock(SoapBody.class);
  when(soapBody.getFault()).thenReturn(soapFault);

  SoapMessage soapMsg = Mockito.mock(SoapMessage.class);
  when(soapMsg.getSoapBody()).thenReturn(soapBody);

  doThrow(new SoapFaultClientException(soapMsg)).when(mockObj).sendSourceAndReceiveToResult(anyString(), any(StreamSource.class), any(StreamResult.class));

  return mockObj;
}
Run Code Online (Sandbox Code Playgroud)

这两种用例可能都需要更多代码,但它们可以用于我的目的.


Mic*_*low 5

实际上我不知道是否存在预先配置的模拟对象,但我怀疑是否已经为所有"失败条件"配置了,所以你可以为你的JUnit测试创建一个特殊的Spring ApplicationContext,用替换或使用模拟框架,它是不那么难:-)

我使用了Mockito Mock Framework作为示例(并快速输入),但EasyMock或您首选的模拟框架也应该这样做

package org.foo.bar
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;

public class WebserviceTemplateMockTest {

    private WhateverTheInterfaceIs webServiceTemplate;
    private TestClassInterface testClass;
    private final String inputXml = "bar";


    @Test
    public void testClient(){
        // 
        assertTrue("foo".equals(testClass.callWebService(inputXml));
    }

    /**
     * Create Webservice Mock.
     */
    @Before
    public void createMock() {
        // create Mock
        webServiceTemplate = mock(WhateverTheInterfaceIs.class);
        // like inputXml you need to create testData for Uri etc.
        // 'result' should be the needed result data to produce the
        // real result of testClass.callWebService(...)
        when(webServiceTemplate.sendSourceAndReceiveToResult(Uri, inputXml, new StreamResult(output))).thenReturn(result);
        // or return other things, e.g.
        // .thenThrow(new FoobarException());
        // see mockito documentation for more possibilities
        // Setup Testclass
        TestClassImpl temp = new TestClassImpl();
        temp.setWebServiceTemplate(generatedClient);
        testClass = temp;
    }
}
Run Code Online (Sandbox Code Playgroud)