Spring MVC Test с Hamcrest: как напрямую сравнить узел XML с объектом Java

Я работаю с:

  • Весенний MVC-тест
  • Хэмкрест

Для предмета из коллекции, например:

<collection>
    <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="persona">
        <id>087</id>
        <nombre>Leonardo</nombre>
        <apellido>Jordan</apellido>
        <fecha>1981-07-05</fecha>
    </item>
    ....

Следующие работы:

.andExpect(xpath("collection/item[1]").exists())
.andExpect(xpath("collection/item[1]/*").nodeCount(is(4)))
.andExpect(xpath("collection/item[1]/id").exists())
.andExpect(xpath("collection/item[1]/id").string(is("087")))
.andExpect(xpath("collection/item[1]/id").string(is(personasArray[0].getId())))
.andExpect(xpath("collection/item[1]/nombre").exists())
.andExpect(xpath("collection/item[1]/nombre").string(is("Leonardo")))
.andExpect(xpath("collection/item[1]/nombre").string(is(personasArray[0].getNombre())))
.andExpect(xpath("collection/item[1]/apellido").exists())
.andExpect(xpath("collection/item[1]/apellido").string(is("Jordan")))
.andExpect(xpath("collection/item[1]/apellido").string(is(personasArray[0].getApellido())))

Я хочу знать, возможно ли провести прямое сравнение с объектом, а не для каждого поля, рассмотрим объект с 15-45 полями.

Мне нужно что-то вроде этого:

.andExpect(xpath("collection/item[1]/*").how(is(personasArray[0])))

См. часть how, она показывает, какой правильный метод использовать. То же самое касается содержимого строки path.


person Manuel Jordan    schedule 13.09.2016    source источник


Ответы (1)


Можно сделать такое утверждение. Но вам нужно будет написать собственный ResultMatcher для этого. Я не думаю, что это хорошая идея преобразовывать XML (узлы) в объекты Java только для простого сравнения в модульном тесте. Вы можете столкнуться с проблемами с разрешением пространства имен XML или контрактом Java hashCode equals, если они не реализованы правильно.

Вместо этого вы должны использовать библиотеки, которые позволят вам сосредоточиться на модульных тестах, а не на деталях технологии или языка программирования.

Я рекомендую вам использовать в тесте XMLUnit. XMLUnit — это библиотека Java для сравнения XML.

В приведенном ниже примере показано, как легко сравнить XML-документ с помощью XMLUnit и пользовательского файла ResultMatcher.

import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultMatcher;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.xmlunit.builder.Input;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.xmlunit.matchers.CompareMatcher.isSimilarTo;

@RunWith(SpringRunner.class)
@WebMvcTest(XmlUnitDemoTests.XmlUnitDemo.class)
public class XmlUnitDemoTests {

    static final String XML_CONTENT = "<node1><node2 id=\"1\">text</node2></node1>";

    @Autowired
    MockMvc mockMvc;

    @Test
    public void xmlUnit() throws Exception {
        mockMvc.perform(get("/xml"))
            .andExpect(xml(XML_CONTENT));
    }

    static ResultMatcher xml(String bodyValue) {
        return MockMvcResultMatchers.content().source(equalXml(bodyValue));
    }

    static Matcher equalXml(String value) {
        return isSimilarTo(Input.fromString(value).build());
    }

    @SpringBootApplication
    @RestController
    static class XmlUnitDemo {

        @RequestMapping(value = "xml", produces = "text/xml")
        String xml() {
            return XML_CONTENT;
        }
    }

}

Конечно, вы можете загружать большие XML-файлы из пути к классам или выбирать узел с XPatch, прежде чем выполнять сравнение. Взгляните на документацию XMLUnit для получения дополнительной информации об этом.

person ksokol    schedule 02.10.2016
comment
Спасибо за ваш пост, я проверю ваше ценное предложение. Теперь насчет I don't think it is a good idea to convert XML (nodes) to Java objects just to do a simple comparison in a unit test я бы согласился. Я понимаю вашу точку зрения, конечно, справедливо, но я должен предположить, что удаленный клиент имеет технологию OXM. Я работаю с Джексоном для XML и JSON. - person Manuel Jordan; 02.10.2016
comment
Вы лучше разбираетесь в настройке своего проекта, и вы единственный, кто может принять правильное решение. Я просто хочу поделиться с вами своим мнением и опытом. - person ksokol; 02.10.2016
comment
Я не говорю, что ваше мнение ошибочно. Я согласен, но я хочу сделать quick кодификацию @Test. Представьте, что вы добавляете или выполняете рефакторинг классов предметной области. Я проверю ваше предложение. Это ценно. Все нормально. Еще раз спасибо за ваш пост. - person Manuel Jordan; 02.10.2016
comment
Я просто хочу вежливо сказать, что вы знаете детали своего проекта, и, следовательно, только вы можете решить, какой из вариантов лучше применить — а или б. Здесь нет каламбура. Продолжай кататься :-) - person ksokol; 02.10.2016