How to use Mockito to test SOAP messages?

I'm fairly new to Mockito, and figured I would try to use it to test a SOAP Handler. However, this is turning out to be a much more painful than I would have expected/desired.

I'm looking to validate that my handler is able to extract the messageID in the header of a SOAPMessage. However, from the handler, the only way to get to the header is via the context/message/part/envelope/header. Using Mockito my solution was to mock my SOAPMessage, meant creating each individual object, and stubbing the method.

I can only imagine that there is an easier/cleaner way of accomplishing this:

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

Like I said, it works, but it looks like a very ugly/heavy weight solution.

Is there anyway to do this easier/cleaner?

Thanks!

Eric


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

Please also pay attention to the notes on using deep stubs in the mockito documentation. http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#RETURNS_DEEP_STUBS

Annotation style:

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

A bit late here, but I prefer spawning a working Endpoint which proxies a mockito mock. This lets me test the whole stack, including interceptors and/or handlers, which should be helpful for your use-case.

I've put up a simple JUnit Rule which simplifies things somewhat here. The resulting test-cases should be small and clean. I recommend loading test XML responses directly from XML files, because that is faster and more simple to maintain.


Don't mock things like this.

Listen to the code... its telling you that this is not the right way to do it.

Rather, just create a (real) message that has some known data in it, and assert that your code does the right stuff with it.

eg

MessageIdExtractor extractor = new MessageIdExtractor(); // <- class you are testing

String expectedMessageId = "xxxxxx";

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

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

链接地址: http://www.djcxy.com/p/57548.html

上一篇: 我怎样才能防止第三方调用某些方法?

下一篇: 如何使用Mockito测试SOAP消息?