Mock de un WS mediante Spring WS

De Dos Ideas.
Saltar a: navegación, buscar

Introducción

En esta página explicaremos de qué forma podemos simular el entorno de un Web Service en memoria, de modo tal de poder realizar un test de componentes contra dicho entorno.

Requerimientos

Para mockear un Web Service mediante Spring WS, necesitaremos agregar a nuestro proyecto los siguientes jars:

  • jaxb-api-2.0.jar
  • jaxb-impl-2.0.3.jar
  • xalan-2.7.1.jar (importante que sea esta versión o superior)
  • xmlunit-1.1.jar

Ejemplo

Básicamente, el código para crear un test contra dicho entorno será como el siguiente:

@RunWith(SpringJUnit4ClassRunner.class)

// indicamos a Spring que levante los archivos de configuración que veremos más adelante @ContextConfiguration("spring-configuration.xml") public class ClienteIntegracionTest {

// Creamos el request a enviarle al WS private String request = "<ns2:ClienteRequest xmlns:ns2='http://ejemplo.com.ar/'><ns2:APELLIDO_RAZONSOCIAL>Una razon social</ns2:APELLIDO_RAZONSOCIAL></ns2:ClienteRequest>";

// Creamos el response que nos responderá el WS private String response = "<ns2:ClienteResponse xmlns:ns2='http://ejemplo.com.ar/'><ns2:ID_CLIENTE>123</ns2:ID_CLIENTE></ns2:ClienteResponse>";

//Inyectamos el WebServiceTemplate @Autowired private WebServiceTemplate webServiceTemplate;

// Mockeamos el WebServiceServer private MockWebServiceServer server;

// Clase nuestra que lo consumirá @Autowired private Cliente cliente;

// En el Before levantamos el server pasandole como parámetro al constructor // el webServiceTemplate @Before public void setup() { server = MockWebServiceServer.createServer(webServiceTemplate); }

@Test public void testInvocacionWs() {

// Le damos comportamiento a nuestro WS con el request y el response // antes configurado server.expect(RequestMatchers.payload(new StringSource(request))).andRespond(ResponseCreators.withPayload(new StringSource(response)));

cliente.invocarMetodoQueLlamaAlWs();

// Nos aseguramos que el servicio fue invocado server.verify(); }

}

Dentro de los archivos de configuración que levante Spring, tendremos que configurarle los siguientes beans:

<bean id="wsTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
 <property name="defaultUri" value="http://localhost:8080/" />
 <property name="marshaller" ref="marshaller" />
 <property name="unmarshaller" ref="marshaller" />
</bean>
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
 <property name="classesToBeBound">
  <list>
   <value>com.dosideas.ejemplo.schemas.ClienteRequest</value>
   <value>com.dosideas.ejemplo.schemas.ClienteResponse</value>
  </list>
 </property>
</bean>

Finalmente, el método de nuestra clase cliente, deberá contener

public void invocarMetodoQueLlamaAlWs() { ... ClienteRequest clienteRequest = new ClienteRequest(); ... ClienteResponse clienteResponse = (clienteResponse) webServiceTemplate

       .marshalSendAndReceive(clienteRequest);

... }

Otra forma de generar un mock

Spring WS Test project es una libreria que simplifica los test que realizamos utilizando spring-ws.

Requerimientos

  • spring-ws-test.jar

Ejemplo

Básicamente, el código para crear un test será como el siguiente:

@RunWith(SpringJUnit4ClassRunner.class) // indicamos a Spring que levante los archivos de configuración que veremos más adelante @ContextConfiguration(locations = {"spring-configuration.xml", "spring-ws-responses-mock.xml"})

public class ClienteComponenteTest {

// Clase nuestra que lo consumirá @Autowired private Cliente cliente;

@Test public void testInvocacionWs() {

Collection<Algo> coleccion = cliente.invocarMetodoQueLlamaAlWs(param1);
assertNotNull(coleccion )

}

}

En nuestra clase de test, debemos agregar al contexto de spring un xml (ej: spring-ws-responses-mock.xml) con la siguiente configuracion:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
   <bean id="messageSender" class="net.javacrumbs.springws.test.MockWebServiceMessageSender"/>
   <bean class="net.javacrumbs.springws.test.util.MockMessageSenderInjector"/>
   <bean class="net.javacrumbs.springws.test.generator.DefaultResponseGeneratorFactoryBean">
       <property name="namespaceMap">
           <map>
               <entry key="soapenv" value="http://schemas.xmlsoap.org/soap/envelope/"/>
           </map>
       </property>
       <property name="XPathExpressions">
           <list>
               <value>concat('/com/tma/dosideas/ws/mock/response/',local-name(//soapenv:Body/*[1]),'-response-', //APELLIDO_RAZONSOCIAL, '.xml')</value>
           </list>
       </property>
   </bean>

</beans>

En la primera parte del xml declaramos un mock message sender que luego inyectamos en nuestro WebServiceTemplate de spring-ws para que las peticiones del template sean atendidas por el mock.

La clase DefaultResponseGeneratorFactoryBean se encarga de buscar en los archivos de un directorio, el xml de response. Para saber cual xml de response corresponde al request, se utiliza xpath sobre el nombre de los archivos del directorio.

Ejemplo:

Si el request es el siguiente:

<?xml version="1.0" encoding="UTF-8"?> <ns2:ClienteRequest xmlns:ns2='http://ejemplo.com.ar'> <ns2:APELLIDO_RAZONSOCIAL>Una razon social</ns2:APELLIDO_RAZONSOCIAL> </ns2:ClienteRequest>

En el directorio "/com/tma/dosideas/ws/mock/response/" se buscara el xml con el siguiente nombre: ClienteRequest-response-Una razon social.xml

El response del directorio es:

<?xml version="1.0" encoding="UTF-8"?> <ns2:ClienteResponse xmlns:ns2='http://ejemplo.com.ar'> <ns2:ID_CLIENTE>123</ns2:ID_CLIENTE> </ns2:ClienteResponse>

Fuente