2012-02-15 35 views
7

Soy bastante nuevo para Mockito, y pensé que intentaría usarlo para probar un Controlador SOAP. Sin embargo, esto está resultando ser mucho más doloroso de lo que hubiera esperado/deseado.¿Cómo usar Mockito para probar mensajes SOAP?

Estoy tratando de validar que mi controlador puede extraer el ID de mensaje en el encabezado de un SOAPMessage. Sin embargo, desde el controlador, la única manera de llegar al encabezado es a través del contexto/mensaje/parte/sobre/encabezado. Usando Mockito mi solución fue burlar mi SOAPMessage, significaba crear cada objeto individual y anular el método.

sólo puedo imaginar que hay una manera más fácil/más limpio para lograrlo:

@RunWith(MockitoJUnitRunner.class) 
public class UUIDHandlerTest { 

    @Mock private SOAPMessage message; 
    @Mock private SOAPEnvelope envelope; 
    @Mock private SOAPHeader header; 
    @Mock private SOAPPart part; 

    @Mock 
    private SOAPMessageContext context; 

    @Before 
    public void setup() throws SOAPException{ 
     when(context.getMessage()).thenReturn(message); 
     when(message.getSOAPPart()).thenReturn(part); 
     when(part.getEnvelope()).thenReturn(envelope); 
     when(envelope.getHeader()).thenReturn(header); 
    } 


    @Test 
    public void testHandleInboundMessage() { 
     when(context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).thenReturn(false); 

     when(header.getElementsByTagName(anyString())).thenAnswer(new Answer<NodeList>() { 
      /* (non-Javadoc) 
      * @see org.mockito.stubbing.Answer#answer(org.mockito.invocation.InvocationOnMock) 
      */ 
      @Override 
      public NodeList answer(InvocationOnMock invocation) throws Throwable { 
       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
       DocumentBuilder db = dbf.newDocumentBuilder(); 
       Document doc = db.parse(new ByteArrayInputStream(new String("<wsa:MessageID>messageId</wsa:MessageID>").getBytes())); 

       // TODO Auto-generated method stub 
       return doc.getElementsByTagName("wsa:MessageID"); 
      } 

     }); 


     // call the test class 
     new UUIDHandler().handleMessage(context); 

     // check the MDC value 
     assertEquals("messageId", MDC.get(LoggerConstants.DC_PROPERTY_MESSAGE_ID)); 
    } 
} 

Como he dicho, funciona, pero parece una solución muy feo peso/pesada.

¿Hay alguna forma de hacer esto más fácil/limpiador?

Gracias!

Eric

Respuesta

3
SOAPMessageContext context = 
      mock(SOAPMessageContext.class, RETURNS_DEEP_STUBS); 
    when(context.getMessage().getSOAPPart().getEnvelope(). 
      getHeader().getElementsByTagName(anyString())). 
      then(...); 

Tenga también en cuenta las indicaciones sobre el uso de los talones de profundidad en la documentación Mockito. http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#RETURNS_DEEP_STUBS

estilo Anotación:

@Mock(answer = Answers.RETURNS_DEEP_STUBS) SOAPMessageContext context; 
+0

Gracias. Justo lo que estaba buscando. –

+0

De acuerdo con los documentos, sin embargo, se debe evitar el uso de RETURN_DEEP_STUBS tanto como sea posible. En cuyo caso, supongo que la pregunta es, ¿cuál es una buena metodología para realizar este tipo de [email protected] time4tea parece indicar que tiene más sentido crear un SOAPMessage real, pero mi concepto completo de usar Mocks es evitar la necesidad de crear una estructura complicada solo para probar. Cualquier consejo sería bienvenido. –

+1

En serio, no hagas esto. Terminará con un código que no comprende, que es muy frágil y que prueba la implementación de todo, no solo su código. Considere usar una solicitud SOAP real (si es posible construir una), o incluso crear un servidor que devuelva un bit conocido de xml, y verifique que su clase extraiga el bit de información correcto de la misma. – time4tea

0

no haga pasar ningún cosas simulacros como este.

Escuche el código ... es diciéndole que esta no es la manera correcta de hacerlo.

Más bien, simplemente cree un mensaje (real) que contenga algunos datos conocidos y afirme que su código hace lo correcto con él.

p. Ej.

MessageIdExtractor extractor = new MessageIdExtractor(); // < - clase que está probando

Cadena expectedMessageId = "xxxxxx";

Mensaje m = new SOAPMessage() .setMessageId (expectedMessageId);

assertThat (extractor.extractIdFrom (m), equalTo (expectedMessageId));

+2

Claro, excepto que no es tan fácil crear el SOAPMessage, y en consecuencia, estaba buscando una forma de hacerlo usando un objeto simulado en su lugar. –

1

Un poco tarde aquí, pero prefiero generar un punto final funcional que simule un falso simulacro. Esto me permite probar toda la pila, incluidos los interceptores y/o controladores, lo que debería ser útil para su caso de uso.

He puesto una regla de JUnit simple que simplifica un poco las cosas here. Los casos de prueba resultantes deben ser pequeños y limpios. Recomiendo cargar respuestas XML de prueba directamente desde archivos XML, porque es más rápido y más fácil de mantener.

Cuestiones relacionadas