【问题标题】:JMockit - mock CXF webservice port objectJMockit - 模拟 CXF 网络服务端口对象
【发布时间】:2014-05-07 05:17:41
【问题描述】:

我正在尝试对尝试隐藏所有 Web 服务实现细节的 Web 服务包装类进行单元测试。它是从脚本平台调用的,因此所有接口都是简单的字符串或整数。该类提供了一个静态初始化方法,该方法采用主机名和端口号,并使用它来创建私有静态 Apache CXF IRemote 端口实例(从 CXF wsdl2java 生成)。随后调用静态业务方法委托给端口实例。

在对静态包装类进行单元测试时,如何使用 JMockit 模拟 CXF 端口存根?

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

Web 服务的示例行为是,如果我传递值“OK”,那么它会返回一条成功消息,但如果我使用“DUPLICATE”值调用,那么 Web 服务将抛出 MyBusinessException_Exception。

我想我已经设法模拟了 _port 对象,但是业务调用总是返回一个 null Response 对象,所以我怀疑我的 Expectations 没有正确定义“BusinessThing”对象。到目前为止我的测试方法。

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

【问题讨论】:

  • 我想我快到了。我认为我的期望与传入的请求对象的特定实例不匹配。看起来我需要为我的 BusinessMethodRequest 对象提供一个自定义匹配器,它只关心 request.getThing().getValue() 如果可以这样做有内置匹配器,请大喊。

标签: unit-testing cxf webservice-client jmockit


【解决方案1】:

似乎工作如下。

为我的 BusinessMethodRequest 添加了一个自定义 Matcher 类

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

然后在我的期望中使用“with”。

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

模拟对象现在可以识别具有正确参数的业务方法调用并返回预期的响应对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多