我正在爲我的Java應用程序編寫單元測試,我需要爲可能引發的潛在JiBX異常編寫一個測試。我正在測試的方法調用另一個類的方法,其中JiBX異常可能會被拋出。這是我測試的類(姑且稱之爲A類):可以使用Mockito來模擬org.jibx.runtime.BindingDirectory嗎?
@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,但是當我試圖模擬JiBXExceptioin for .getRequest時,Mockito說「檢查異常對於此方法無效」。如果我不能讓Mockito拋出這個錯誤,我不知道是否可以操縱關聯的對象來拋出它。
其實這是一個很好的解決方案。創建僅用於測試的新方法沒有任何問題。最好有一個很好的可測試的類,而不是少一個方法。新方法必須是包私有的,這非常合適。這種類型的問題是間諜少數真正的好用途之一。還有另一種方法可以做到這一點,您可能更喜歡 - 我會在幾個小時內發佈答案(如果我記得的話)。 – 2012-08-08 02:23:48