我正在为Java应用程序编写单元测试,并且需要为可能引发的JiBX异常编写测试。我正在测试的方法从另一个类调用一个方法,该类可能会引发JiBX异常。这是我正在测试的课程(我们称其为A类):

@Inject
private CommonDAL commonDAL;

@Async
public Future<String> getTransactionalXXXAvailability(
        List<XXXAvailRequestEntry> requestEntries, TravelWindow travelWindow) {
    if (requestEntries.size() == 0)
        return null;
    XXXAvailRqAccessor requestAccessor = new XXXAvailRequestBuilder().buildRequest(requestEntries, travelWindow);
    logger.info(requestAccessor.marshalRequest());
    String responseAsXml = null;
    try {
        responseAsXml = getResponse(requestAccessor.getRequest());
    } catch (JiBXException e) {
        logger.error("Problem unmarshaling the XXX avail response: ", e);
    }

    logger.info(responseAsXml);
    return new AsyncResult<String>(responseAsXml);
}

private String getResponse(OTAXXXAvailRQ request) throws JiBXException {
    HbsiConnectionInfo connectionInfo = new HbsiConnectionInfo();
    connectionInfo.useConnectionInfoFromContext();

    HBSIXML4OTAWebserviceSoap hbsiSoap = getHbsiSoapService(connectionInfo);

    InterfacePayload header = new InterfacePayload();
    header.setChannelIdentifierId("XXXXXXXXX");
    header.setVersion("2005B");
    header.setInterface("HBSI XML 4 OTA");

    ComponentInfo componentInfo = new ComponentInfo();
    XXXAvailRqAccessor requestAccessor = new XXXAvailRqAccessor(request);
    componentInfo.setId(requestAccessor.getFirstXXXCode());
    componentInfo.setUser( connectionInfo.getUsername() );
    componentInfo.setPwd( connectionInfo.getPassword() );
    componentInfo.setComponentType(EComponentType.XXX);

    Login login = new Login();
    login.setComponentInfo(componentInfo);

    Message body = new Message();
    // todo: this needs to be unique for every request.
    // todo: hook up to logging
    body.setRequestId(UUID.randomUUID().toString());
    body.setTransaction(ETransaction.XXX_AVAIL_RQ);

    body.setXML(requestAccessor.marshalRequest());

    return hbsiSoap.getSoapRequest(header, body, login);
}

HBSIXML4OTAWebserviceSoap getHbsiSoapService(HbsiConnectionInfo connectionInfo) {
    HBSIXML4OTAWebservice ws = new HBSIXML4OTAWebservice( connectionInfo.getWsdlLocation() );

    HBSIXML4OTAWebserviceSoap hbsiSoap = ws.getHBSIXML4OTAWebserviceSoap();
    Map<String, Object> requestContext = ((BindingProvider)hbsiSoap).getRequestContext();
    String readTimeout = commonDAL.getPropertyValue(new PropertyKey(Section.HBSI,
            Property.HBSI_WS_READ_TIMEOUT));
    requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, Integer.parseInt(readTimeout));
    String connectionTimeout = commonDAL.getPropertyValue(new PropertyKey(Section.HBSI,
            Property.HBSI_WS_CONNECTION_TIMEOUT));
    requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, Integer.parseInt(connectionTimeout));
    return hbsiSoap;
}


引发错误的方法如下(在另一个类中,我们称其为B类):

public String marshalRequest() {
    StringWriter requestAsXml = new StringWriter();

    try {
        IBindingFactory bindingFactory = BindingDirectory.getFactory(PROTECTEDCLASSNAME.class);
        IMarshallingContext marshalingContext = bindingFactory.createMarshallingContext();
        marshalingContext.setIndent(2);
        marshalingContext.setOutput(requestAsXml);
        marshalingContext.marshalDocument(request);

    } catch (JiBXException e) {
        logger.error("Problem marshaling PROTECTEDCLASSNAME.", e);
    }

    return requestAsXml.toString();
}


当“ body.setXML(requestAccessor.marshalRequest());”时会被调用,测试将访问另一个类(requestAccessor),它的方法.marshalRequest是应该引发JiBX异常的位置。我正在编写测试的目的是使A类的单元测试覆盖率达到100&,但是受测系统至少由两个类组成,因为我无法模拟称为requestAccessor的XXXAvailRqAccessor对象。由于以下原因,我无法进行任何测试来产生此错误。


在我正在测试的方法中实例化了称为requestAccessor的XXXAvailRqAccessor对象,因此无法使用模拟程序引发异常。
无法模拟传递给.getResponse()的OTAXXXAvailRQ参数,因为它是由XXXAvailRqAccessor的构建器创建的。
我尝试在IBindingFactory上进行监视,但没有成功。我在B类中创建了一个将实例化IBindingFactory的方法,以便可以对其进行监视,但这种方法无效。
我还尝试使用PowerMock在实例化时返回模拟XXXAvailRqAccessor,但是,当我尝试模拟.getRequest的JiBXExceptioin时,Mockito说“已检查的异常对该方法无效”。如果无法让Mockito抛出此错误,我不知道是否有可能操纵关联的对象来抛出该错误。

最佳答案

好吧,不是真的,或者至少我不知道这种方式。您可以,如果您确实要这样做(我反对),则可以在该类中创建一个像这样的方法:

IBindingFactory getBindingFactory() {
    return BindingDirectory.getFactory(PROTECTEDCLASSNAME.class);
}


并替换此行:

IBindingFactory bindingFactory = BindingDirectory.getFactory(PROTECTEDCLASSNAME.class);


带有:

IBindingFactory bindingFactory = getBindingFactory();


然后,您可以spy()(如果您不熟悉它,可以在文档中阅读Mockito.spy()),然后使此方法返回一个模拟。从那时起,航行顺畅。

尽管不建议使用此方法,因为:


您正在创建一种仅用于测试的新方法(一种无用的方法)
所述方法必须对测试可见,因此您不能将其标记为私有...
我一般不是间谍的忠实拥护者


问题仍然是:如何正确测试这种情况。在大多数情况下,我会尝试尽可能多地重构,有时它会有所帮助。在其他情况下...嗯,我仍然没有想出更好的解决方案。

关于java - 可以使用Mockito模拟org.jibx.runtime.BindingDirectory吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11846578/

10-11 22:16
查看更多