13

XSD を使用せずに Jaxb 2.0 API を使用しており、注釈を使用してコンテンツ モデルを作成しました。マーシャリングを行うクラスの Junit テストを書きたいと思います。私の当初の計画は、予想される XML 文字列を実際のアサーション (最も明白な選択) と比較することでした。しかし、マーシャリングにより、プロパティ/属性の順序が予測できないxmlが作成されることがわかりました(実際、デフォルトの順序はわかりません)。この場合、事前定義された xml 文字列を仮定して、これをマーシャリングされたものと比較することはできません。マーシャラークラスをアサートするために私が考えていた別の方法は次のとおりです。

1-コンテンツ モデルを作成します。

2-マーシャリングします。

3-手順 2 で作成した xml をアンマーシャリングして、モデルを取得します。

4-ステップ 1 とステップ 3 のモデルに基づいて、プロパティ/属性についてアサーションを実行します。

しかし、私はまだこれで満足しているとは思いません。このシナリオでマーシャリング用の Junit テストを作成する正しい方法は何でしょうか?.

整列化された xml を使用する実際のアプリケーションは xml のプロパティ/属性の順序に依存しませんが、Junit テストはややこしいようです。

ありがとう

4

4 に答える 4

11

同じことをグーグルで調べているときに、あなたの質問に出くわしました。この投稿を見つけたが、後で生成された XML を「解析」する必要があるという考えが気に入らなかった場合。JAXB Javadoc をふるいにかけた後、私は非常に気に入っているアプローチを見つけました。JAXBは、SAXを引数としてMarshaller取るメソッドを提供します。ContentHandlerそれをモックしてContentHandler、特定のメソッドが予想される引数で呼び出されたことを確認できます。

ここに少し例があります。Attributes特定の属性のローカル名の存在のみを検証し、値は (まだ) 確認しないカスタムマッチャーを作成しました。これがお役に立てば幸いです:

@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());
}
于 2012-11-18T21:24:18.750 に答える
4

私は、XML マーシャリング テストで同じ問題に直面しました。XmlUnitライブラリを使用して、シリアル化された xml をエタロンと比較できます。XmlUnit は 2 つの xml を比較でき、スペースの無視、要素の並べ替えなどの機能をサポートします。

XmlUnit に関するIBM developerWorks の優れた記事は、
XmlUnit の古いバージョンについて説明していますが、適切な説明と例を示しています。

xml を比較すると、次のようになります。

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

    assert !diff.hasDifferences()
于 2016-06-13T00:51:20.793 に答える
0

実際には、jaxb によって生成されたものと比較するために期待される結果を書くことができます。アサーション エラーを引き起こす可能性がある期待される結果の最後に「\n」を追加することを忘れないでください。

于 2012-12-13T05:48:03.110 に答える