2012-08-25 22 views
10

Estoy usando Jaxb 2.0 api sin usar XSD, y he creado el modelo de contenido usando anotaciones. Quiero escribir una prueba de Junit para la clase que hace la clasificación. Mi plan original era comparar el XML String esperado con el real para la aserción (la opción más obvia). Pero me parece que el marshalling crea xml donde el orden de propiedades/atributos no es predecible (en realidad no sé cuál es el orden predeterminado). Ahora bien, si este es el caso, no puedo suponer una Cadena xml predefinida y luego comparar esto con el marshalled. Otra forma en que estaba pensando para afirmar la clase marshaller fue la siguiente:Cómo escribir un test de unidad para JAXB 2.0 Marshalling

1-Create content Model.

2-Marshall it.

3-Unmarshall el xml creado en el paso 2 para obtener el modelo.

4-Haga la aserción basada en el modelo en el paso 1 y el paso 3 para propiedades/atributos.

Pero todavía no encuentro esto satisfactorio. ¿Cuál sería la forma correcta de escribir una prueba de Junit para organizar en este escenario?

Aunque la aplicación real que utiliza el xml marshalled no depende del orden de propiedades/atributos xml, pero la prueba de Junit parece ser complicada.

Gracias

Respuesta

6

me topé con su pregunta mientras que buscando en Google para la misma cosa. Si encontró este post, pero no le gustó la idea de tener que "analizar" el XML generado posteriormente. Después de pasar por el JAXB Javadoc, encontré un enfoque que me gusta bastante. Un JAXB Marshaller ofrece un método que toma un SAX ContentHandler como argumento. Puede simular ese ContentHandler y verificar que se hayan invocado los métodos específicos con los argumentos esperados.

Aquí hay un pequeño ejemplo. Escribí un marcador personalizado Attributes que solo verifica la presencia de ciertos nombres locales de atributos, pero no mira los valores (todavía). Espero que encuentre útil esta información:

@Mock 
private ContentHandler handler; 

private JAXBContext context; 
private ObjectFactory factory; 
private Marshaller marshaller; 

@Before 
public void setUp() throws Exception 
{ 
    context = JAXBContext.newInstance(getClass().getPackage().getName()); 
    factory = new ObjectFactory(); 
    marshaller = context.createMarshaller(); 
} 

@Test 
public void test() throws Exception 
{ 
    final UpdateDescription description = new UpdateDescription("identifier", "version"); 
    final JAXBElement<UpdateDescription> element = factory.createUpdateDescription(description); 

    marshaller.marshal(element, handler); 

    verify(handler).startDocument(); 
    verify(handler).startElement(anyString(), eq("description"), anyString(), any(Attributes.class)); 
    verify(handler).startElement(anyString(), eq("identifier"), anyString(), attrs("value")); 
    verify(handler).startElement(anyString(), eq("version"), anyString(), attrs("value")); 
    verify(handler).endDocument(); 
} 

private static Attributes attrs(final String... localNames) 
{ 
    final Matcher<Attributes> matcher = new TypeSafeMatcher<Attributes>() 
    { 
     private Set<String> names = Sets.<String> newHashSet(localNames); 

     @Override 
     public void describeTo(final Description description) 
     { 
      // TODO Auto-generated method stub 
     } 

     @Override 
     public boolean matchesSafely(final Attributes item) 
     { 
      final Set<String> presentLocalNames = Sets.newHashSetWithExpectedSize(item.getLength()); 
      final int length = item.getLength(); 
      for (int i = 0; i < length; ++i) { 
       presentLocalNames.add(item.getLocalName(i)); 
      } 

      return Sets.difference(names, presentLocalNames).isEmpty(); 
     } 
    }; 
    return new ThreadSafeMockingProgress().getArgumentMatcherStorage().reportMatcher(matcher).returnFor(
      new AttributesImpl()); 
} 
+0

me gusta la forma en que esto se ve, pero puede proporcionar más de un ejemplo? –

0

realidad se puede escribir el resultado esperado de comparar con lo que se genera por jaxb, no se olvide de añadir "\ n" en el final de su resultado esperado que es probable que cause la afirmación de error

3

Para aquellos que prefieren una prueba más simple, esto es lo que arme del poste vinculado en la respuesta de RobertB, y las respuestas here:

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBElement; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 
import javax.xml.namespace.QName; 
import javax.xml.transform.stream.StreamSource; 

public class JaxbTestHelper { 

    @SuppressWarnings({ "rawtypes", "unchecked" }) 
    public static Object jaxbMarshalUnmarshal(Object schemaObject) throws Exception { 
     JAXBContext context = JAXBContext.newInstance(schemaObject.getClass()); 
     Marshaller marshaller = context.createMarshaller(); 
     Unmarshaller unmarshaller = context.createUnmarshaller(); 
     ByteArrayOutputStream output = new ByteArrayOutputStream(); 
     Object unmarshalledObject = null; 

     try { 
      marshaller.marshal(schemaObject, output); 
      ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray()); 
      unmarshalledObject = unmarshaller.unmarshal(input); 
     } catch (JAXBException e) { 
      // object class not annotated with @XmlRootElement, so we have to "wrap" and "unwrap" the object 
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
      marshaller.marshal(new JAXBElement(new QName("uri", "local"), schemaObject.getClass(), schemaObject), 
        output); 

      StreamSource source = new StreamSource(new ByteArrayInputStream(output.toByteArray())); 
      unmarshalledObject = unmarshaller.unmarshal(source, schemaObject.getClass()).getValue(); 
     } 

     // callers should verify this returned object equals the schema object passed in 
     // ie, mySchemaObject.equals(jaxbMarshalUnmarshal(mySchemaObject)) 
     return unmarshalledObject; 
    } 

} 

3

Me enfrenté con el mismo problema de las pruebas de clasificación XML. Puede usar la biblioteca XmlUnit para comparar su xial serializado con etalon. XmlUnit puede comparar dos xml y admite funciones como ignorar espacio, reordenamiento de elementos y alguna otra.

Aquí es buen artículo de IBM developerWorks about XmlUnit,
Si bien se describe la versión más antigua de XMLUnit, da buena explicación y ejemplos.

Compara de XML puede tener este aspecto:

Diff diff = DiffBuilder 
      .compare(expectXml) 
      .withTest(marshaledXml) 
      //Ignore element order 
      .withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byName)) 
      .ignoreWhitespace() 
      .ignoreComments() 
      .checkForSimilar() 
      .build() 

    assert !diff.hasDifferences() 
Cuestiones relacionadas