views:

77

answers:

3

I want to write a unit test for some code that generates a SOAP message with an attachment and sends it:

SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance();
conn = factory.createConnection();
conn.call(message, endpoint);

where the factory is a javax.xml.soap.SOAPConnectionFactory

I don't care about any response coming back but I want to be able to verify the message that gets sent. The code is going to be refactored and I want to make sure it sends that same messages afterwards as before.

Is there a framework i can use to create a mock endpoint that will let me analyse the request in my test? If so, some sample code would be very useful.

+3  A: 

There is a java.net project called WSUnit that should help. It is basically a listener servlet which listens for messages. You can send messages to it and verify the content of the message using XMLUnit.

Faisal Feroz
This sounds like what I want, I'll check it out and report back here.
Alb
@Faisal Thanks, I've added my own answer and explained in it why I went with jetty instead for my particular case.
Alb
+1  A: 

Use JMock. JMock allows you to test for behavior rather than state changes. To do this, you'll need to encapsulate the SOAPCOnnectionFactory.newInstance() method in a diffent object:

public class MySOAPConnectionFactory {

    public SOAPConnectionFactory getConnection() {
        return SOAPConnectionFactory.newInstance();
}

Use an object of the new class in your code.

conn = mySOAPConnectionFactory.getConnection();
conn.call( message, endpoint );

Then, in your test, substitute a Mock object for the Factory, which will return a Mock Connection. Set expectations on the Mock Connection expecting the call you're looking for.

final SOAPConnectionFactory mockConnection = mockery.mock(SOAPConnectionFactory.class);
final SOAPConnection mockSoapConnection = mockery.mock(SOAPConnection.class);
foo.setMySOAPConnectionFactory( mockConnectionFactory );
try {
        mockery.checking( new Expectations() {

        {
            atLeast( 1 ).of( mockConnectionFactory ).getConnection();
            will( returnValue( mockSoapConnection ) );
            atLeast( 1 ).of( mockConnection ).call(SOME_MESSAGE, ENDPOINT);
        }
        } );
Matthew Flynn
@Matthew Thanks but I want to test at a different level to this, I want the actual connection to create whatever HTTP SOAP request it will send, and then I want to verify the contents of that.
Alb
Ah. Aren't you at that point testing the implemetation of SOAPConnection rather than your code?
Matthew Flynn
@Matthew I'm testing what the code actually sends to Web Service. I want to ensure that if the code changes, even the library being used (axis) that the same request is sent. I know ideally each class should be tested at a finer granularity but time won't permit that.
Alb
Sounds like WSUnit is what you want, then.
Matthew Flynn
A: 

I had a look at WSUnit as suggested in another answer which seems to be available as an eclipse plug-in or as a war I'd deploy to tomcat. It seems overkill that my test would need to depend on either of these things.

I hunted a bit more and found a useful approach using jetty. The code is in 3 unfortunately non-formatted pieces. at http://jpz-log.info/archives/2006/08/16/unit-testing-a-http-client-with-jetty/ I recommend copying and pasting them to an IDE and formatting them there before reading.

The gist of it is to start a Jetty server and dummy servlet (written specifically for the test) within the test and examine the request in the doGet or doPost methods of the servlet.

Alb