2012-08-25 27 views
10

Tôi đang sử dụng api Jaxb 2.0 mà không sử dụng XSD và đã tạo mô hình nội dung bằng cách sử dụng chú thích. Tôi muốn viết một bài kiểm tra Junit cho lớp học mà marshalling. Kế hoạch ban đầu của tôi là so sánh chuỗi XML dự kiến ​​với chuỗi thực tế để xác nhận (lựa chọn rõ ràng nhất). Nhưng tôi thấy rằng marshalling tạo xml nơi tài sản/thuộc tính thứ tự là không thể dự đoán (thực sự tôi không biết thứ tự mặc định là gì). Bây giờ nếu đây là trường hợp tôi không thể giả định một xml chuỗi được xác định trước và sau đó so sánh này với một marshalled. Một cách khác tôi đã suy nghĩ để khẳng định lớp marshaller như sau:Cách viết Kiểm tra Đơn vị cho JAXB 2.0 Marshalling

1-Tạo nội dung Mô hình.

2-Marshall.

3-Unmarshall xml được tạo ở bước 2 để lấy mô hình.

Xác nhận 4-Do dựa trên mô hình ở bước 1 và bước 3 cho thuộc tính/thuộc tính.

Nhưng tôi vẫn không thấy điều này thỏa đáng. Điều gì sẽ là cách chính xác để viết một bài kiểm tra Junit cho marshalling trong kịch bản này ?.

Mặc dù ứng dụng thực tế sử dụng xml marshalled không phụ thuộc vào thứ tự thuộc tính xml/thuộc tính, nhưng thử nghiệm Junit có vẻ phức tạp.

Cảm ơn

Trả lời

6

Tôi gặp khó khăn khi đặt câu hỏi của bạn trong khi googling cho cùng một điều. Nếu tìm thấy điều này post, nhưng không thích ý tưởng phải "phân tích" XML được tạo sau đó. Sau khi sàng lọc JAXB Javadoc, tôi đã tìm thấy một cách tiếp cận mà tôi rất thích. Một JAXB Marshaller cung cấp một phương thức lấy SAX ContentHandler làm đối số. Bạn có thể giả thiết rằng ContentHandler và xác minh rằng các phương thức cụ thể đã được gọi với các đối số dự kiến.

Dưới đây là một ví dụ nhỏ. Tôi đã viết một đối sánh Attributes tùy chỉnh chỉ xác minh sự hiện diện của một số tên thuộc tính nhất định, nhưng không xem xét các giá trị (chưa). Tôi hy vọng bạn thấy hữu ích này:

@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

Tôi thích cách này có vẻ, nhưng tôi có thể cung cấp nhiều hơn một ví dụ? –

0

thực sự bạn có thể viết được mong đợi kết quả để so sánh với những gì được tạo ra bởi jaxb, không quên thêm "\ n" ở cuối kết quả mong đợi của bạn mà có thể gây ra các khẳng định lỗi

3

Đối với những người muốn có một thử nghiệm đơn giản, đây là những gì tôi đặt lại với nhau từ đăng bài liên kết trong câu trả lời RobertB, và câu trả lời 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

Tôi phải đối mặt với cùng một vấn đề về kiểm tra marshalling XML. Bạn có thể sử dụng thư viện XmlUnit để so sánh xml được tuần tự hóa với etalon. XmlUnit có thể so sánh hai xml và hỗ trợ các tính năng như bỏ qua không gian, các phần tử sắp xếp lại và một số khác.

Đây là bài viết hay từ IBM developerWorks about XmlUnit,
mặc dù mô tả phiên bản cũ hơn của XmlUnit, nó cung cấp giải thích và ví dụ tốt.

Hãy so sánh của xml có thể trông như thế này:

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

    assert !diff.hasDifferences()