2012-02-15 26 views
7

Sono abbastanza nuovo per Mockito e ho pensato di provare a usarlo per testare un gestore SOAP. Tuttavia, questo si sta rivelando molto più doloroso di quanto mi sarei aspettato/desiderato.Come utilizzare Mockito per testare i messaggi SOAP?

Sto cercando di convalidare che il mio gestore sia in grado di estrarre il messageID nell'intestazione di un messaggio SOAP. Tuttavia, dal gestore, l'unico modo per arrivare all'intestazione è tramite il contesto/messaggio/parte/busta/intestazione. Usando Mockito la mia soluzione era di prendere in giro il mio SOAPMessage, significava creare ogni singolo oggetto e stubare il metodo.

Posso solo immaginare che ci sia un modo più semplice/pulitore di compiere questo:

@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)); 
    } 
} 

Come ho detto, funziona, ma sembra che una soluzione di peso molto brutto/pesante.

Esiste comunque una soluzione più semplice/pulita?

Grazie!

Eric

risposta

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

Si prega di prestare attenzione anche alle note sull'uso stub profonde nella documentazione Mockito. http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#RETURNS_DEEP_STUBS

Annotazione stile:

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

Grazie. Proprio quello che stavo cercando. –

+0

Secondo i documenti, tuttavia, l'utilizzo di RETURN_DEEP_STUBS dovrebbe essere evitato il più possibile. Nel qual caso, suppongo che la domanda diventi, qual è una buona metodologia per eseguire questo tipo di [email protected] time4tea sembra indicare che ha più senso creare un vero SOAPMessage, ma il mio intero concetto di usare Mocks è di evitare di dover creare una struttura complicata solo per il test. Qualsiasi consiglio sarebbe benvenuto. –

+1

Seriamente - non farlo. Finirai con il codice che non capisci, che è molto fragile e che verifica l'implementazione di tutto, non solo del tuo codice. Prendi in considerazione l'utilizzo di una vera richiesta SOAP (se è possibile costruirne una) o anche la creazione di un server che restituisce un bit noto di xml e controlla che la classe estrae il giusto bit di informazioni da esso. – time4tea

0

fare non le cose finte come questa.

Ascolta il codice ... ti dice che questo non è il modo giusto per farlo.

Piuttosto, basta creare un messaggio (reale) che contiene alcuni dati noti e affermare che il proprio codice fa le cose giuste con esso.

ad es.

MessageIdExtractor extractor = new MessageIdExtractor(); // < - classe che si sta testando

String expectedMessageId = "xxxxxx";

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

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

+2

Certo - eccetto che non è così facile creare SOAPMessage, e di conseguenza, cercava un modo per farlo usando invece un oggetto fittizio. –

1

Un po 'tardi qui, ma preferisco generare un Endpoint funzionante che genera un mockito simulato. Ciò mi consente di testare l'intero stack, compresi gli intercettori e/oi gestori, che dovrebbero essere utili per il tuo caso d'uso.

Ho creato una semplice regola JUnit che semplifica alquanto le cose here. I casi di test risultanti dovrebbero essere piccoli e puliti. Raccomando di caricare le risposte XML di test direttamente dai file XML, perché è più veloce e più semplice da mantenere.

Problemi correlati