2017-02-21 70 views
0

У меня есть набор модульных тестов, которые дешифруют сохраненный XML-файл в объекты JAXB. Они работали. Эти тесты использовали PowerMock (1.6.6) из-за одной детали в CUT (тестируемый код), для которого требовалось предложение «whenNew».JAXB жалуется на то, что пространство имен присутствует, когда оно должно быть там

Я решил внести изменения в абстракцию, что за фабрикой объектов, что позволило мне перейти к чистому Мокито.

Когда я это сделал, я начал получать необъяснимые проблемы при разборке XML-файлов в объекты JAXB во время теста. Он просто не хранил некоторые элементы в объектах JAXB.

Метод, который делает демаршаллинг выглядит следующим образом:

protected JAXBElement<?> unmarshallToObject(Node node, Class<?> nodeClassType) throws ServiceException { 
    try { 
     return getUnmarshaller().unmarshal(node, nodeClassType); 
    } catch (JAXBException ex) { 
     baseLogger.error(null, ex, "JAXB Exception while un-marshalling"); 
     throw new ServiceException(UslErrCodes.BACKEND_APP.createServiceErr(BackendConfig.USL.getId(), 
       "JAXB Exception while un-marshalling"), ex); 
    } 
} 

Я изменил его на следующее, чтобы получить больше информации:

protected JAXBElement<?> unmarshallToObject(Node node, Class<?> nodeClassType) throws ServiceException { 
    try { 
     Unmarshaller unmarshaller = getUnmarshaller(); 
     unmarshaller.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); 
     return unmarshaller.unmarshal(node, nodeClassType); 
    } catch (JAXBException ex) { 
     baseLogger.error(null, ex, "JAXB Exception while un-marshalling"); 
     throw new ServiceException(UslErrCodes.BACKEND_APP.createServiceErr(BackendConfig.USL.getId(), 
       "JAXB Exception while un-marshalling"), ex); 
    } 
} 

То, что я обнаружил, что демаршаллинг процесс отказа сохраняйте некоторые элементы в экземплярах JAXB, поскольку они получают ошибки схемы xml.

Например, после изменения этого кода я видел сообщения, подобные приведенным ниже. Я ссылаюсь здесь на пространство имен «http://namespace1.xsd», который, очевидно, не был его оригинальным именем, но все места, где это конкретное пространство имен показано в этих примерах, я использую это имя «namespace1.xsd».

JAXB Exception while un-marshalling:unexpected element (uri:"http://namespace1.xsd", local:"securityFeeRequired"). Expected elements are <{}securityFeeRequired>,<{}proprietarySegmentFlag>,<{}Treatment>,<{}creditScoreMessage>,<{}ServiceEligibility>,<{}warningMessage>,<{}creditScoreResult>,<{}creditBand> 

Как вы можете видеть, документ XML указано, что элемент находится в пространстве имен, но «{}», кажется, подразумевает, что пространство имен не было ожидаемо.

Это отрывок из сгенерированного класса JAXB:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "", propOrder = { "creditScoreResult", "creditScoreMessage", "warningMessage", 
     "securityFeeRequired", "treatment", "creditBand", "proprietarySegmentFlag", "serviceEligibility" }) 
public static class FooResult implements Serializable { 
    private static final long serialVersionUID = 1L; 
    protected String creditScoreResult; 
    protected String creditScoreMessage; 
    protected String warningMessage; 
    protected boolean securityFeeRequired; 

А вот @XmlSchema аннотаций из сгенерированного "пакет-инфо" из того же пакета:

@XmlSchema(namespace="http://namespace1.xsd", elementFormDefault=XmlNsForm.QUALIFIED) 

Итак, после получения этой ошибки я решил попробовать изменить «это не возможно».

Я изменил файл XML, например, что это аналогичный отрывок:

<ExecuteFooResponse xmlns:ns1="http://namespace1.xsd" xmlns:ns2="http://namespace2.xsd"> 
     <FooResult> 
      <securityFeeRequired>false</securityFeeRequired> 
      <Treatment><code>A001</code> 
       <message>No additional fee is required at this time</message> 
      </Treatment> 
      <ServiceEligibility> 
       <productCode>BAR</productCode> 
       <serviceEligibilityIndicator>true</serviceEligibilityIndicator> 
      </ServiceEligibility> 
     </FooResult> 
     <Response> 
      <ns2:code>0</ns2:code> 
      <ns2:description>Success</ns2:description> 
     </Response> 
    </ExecuteFooResponse> 

Единственное изменение, которое я сделал был префикс пространства имен для «namespace1.xsd». Это было неудачно с «" (пробелом), что, насколько я понимаю, является правильным. Я изменил его на «ns1», но только в декларации. Я явно не ссылаюсь на этот префикс в теле элемента. Это делает тест PASS.

Пожалуйста, восстановите мое здравомыслие.

ответ

0

Проблема заключалась в том, что XML-документы, которые использовались в тестах, фактически не были действительными для схемы. У них были тонкие проблемы, из-за которых валидация терпит неудачу, но эти проблемы были намеренно размещены другими разработчиками, потому что они обнаружили, что тесты PowerMock не пройдут без этих ERRORS. Я все еще пытаюсь понять, почему PowerMock будет работать только с файлами в этом состоянии, но мои документы теперь действительны по схеме, и тесты Mockito работают.