Question

I'm trying to unit test a webservice wrapper class which attempts to hide all the webservice implementation details. It's called from a scripting platform so all interfaces are simple String or integers. The class provides a static initialise method which takes the hostname and port number and uses this to create a private static Apache CXF IRemote port instance (generated from CXF wsdl2java). Subsequent calls to a static business method delegate to the port instance.

How can I use JMockit to mock the CXF port stub when unit testing the static wrapper class?

public class WebServiceWrapper {

private static final QName SERVICE_NAME = new QName("http://www.gwl.org/example/service", 
        "ExampleService");
private static IRemoteExample _port = null;

public static final String initialise(String url) {
    if(_port != null) return STATUS_SUCCESS;
    try {
        URL wsdlURL = new URL(url);

        ExampleService svc = new ExampleService(wsdlURL, SERVICE_NAME);
        _port = svc.getIRemoteExamplePort();

        BindingProvider bp = (BindingProvider)_port;
        Map<String, Object> context = bp.getRequestContext();
        context.put(BindingProvider.SESSION_MAINTAIN_PROPERTY, true);

        return STATUS_SUCCESS;
    }
    catch(MalformedURLException ex) {
        return STATUS_ERROR_PREFIX + ex.getMessage();
    }
    catch(WebServiceException ex) {
        return STATUS_ERROR_PREFIX + ex.getMessage();
    }
}

public static final String businessMethod(String arg) {
    if(_port == null) {
        return STATUS_ERROR_PREFIX + "Attempted to call businessMethod before connection is initialised. Pease call initialise first.";
    }

    try {
        BusinessMethodRequest request = new BusinessMethodRequest ();
        BusinessThing thing = new BusinessThing();
        thing.setValue(arg);
        request.setThing(thing);
        BusinessMethodResponse response = _port.businessMethod(request);
        String result = response.getResult();       
        if(result == null) {
            return STATUS_ERROR_PREFIX + "Null returned!";
        }
        return STATUS_SUCCESS;
    }
    catch(MyBusinessException_Exception ex) {
        return STATUS_ERROR_PREFIX + ex.getFaultInfo().getReason();
    }
    catch(WebServiceException ex) {
        return STATUS_ERROR_PREFIX + ex.getMessage();
    }
}

Example behaviour of the webservice would be, if I pass the value "OK" then it returns a success message, but if I call with a value of "DUPLICATE" then the webservice would throw a MyBusinessException_Exception.

I think I have managed to mock the _port object, but the business call always returns a null Response object so I suspect that my Expectations does not define the "BusinessThing" object correctly. My Test method so far.

    @Test
public void testBusinessMethod(@Mocked final IRemoteExample port) {

    new NonStrictExpectations() {
        @Capturing IRemoteExample port2;
        {
            BusinessThing thing = new BusinessThing();
            thing.setValue("OK");
            BusinessMethodRequest req = new BusinessMeothdRequest();
            req.setThing(thing);

            BusinessMethodResponse resp = new BusinessMethodResponse ();
            resp.setResult("SUCCESS");

            try {
                port.businessMethod(req);
                returns(resp);
            }
            catch(MyBusinessException_Exception ex) {
                returns(null);
            }

            Deencapsulation.setField(WebServiceWrapper.class, "_port", port);
        }
    };

    String actual = WebServiceWrapper.businessMethod("OK");
    assertEquals(WebServiceWrapper.STATUS_SUCCESS, actual);
}
Was it helpful?

Solution

Seems to be working as follows.

Added a custom Matcher class for my BusinessMethodRequest

    class BusinessMethodRequestMatcher extends TypeSafeMatcher<BusinessMethodRequest> {

    private final BusinessMethodRequestexpected;

    public BusinessMethodRequestMatcher(BusinessMethodRequest expected) {
        this.expected. = expected;
    }

    @Override
    public boolean matchesSafely(BusinessMethodRequest actual) {
        // could improve with null checks
        return expected.getThing().getValue().equals(actual.getThing().getValue());
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(expected == null ? null : expected.toString());
    }
}

Then use "with" in my Expectation.

    try {
    port.createResource(with(req, new BusinessMethodRequestMatcher(req)));
    returns(resp);
}

The mock object now recognises the business method call with the correct parameter and returns the expected response object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top