Утверждение массива массивов с помощью JSONPath и spring mvc

Мне трудно понять, как утверждать с помощью jsonPath в ответе документа JSON в spring mvc. Возможно, есть лучший способ сделать это, чем использовать jsonPath для этого конкретного сценария. Я хотел бы проверить, что массив ссылок имеет элемент rel "self" и что атрибут "href" объекта "self" также имеет атрибут "href", который равен "/". Ответ JSON выглядит так:

 {  
   "links":[  
      {  
         "rel":[  
            "self"
         ],
         "href":"/"
      },
      {  
         "rel":[  
            "next"
         ],
         "href":"/1"
      }
   ]
}

Я попробовал это, где я вижу, что у него есть rel [0], есть self, но я бы предпочел не полагаться на то, где в массиве ссылок и массиве rel находится self, и на самом деле проверить, что это за href в links[rel][self] является "/". Любые идеи?

 @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
    mockMvc = MockMvcBuilders.standaloneSetup(welcomeController).build();
  }

  @Test
  public void givenRootUrl_thenReturnLinkToSelf() throws Exception {
    mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
        .andExpect(jsonPath("$.links[0].rel[0].", is("self")));
  }

person Magnus Lassi    schedule 02.09.2014    source источник


Ответы (3)


Как насчет добавления нескольких методов andExpect? Что-то похожее:

mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk())
    .andExpect(jsonPath("$.links[0].rel[0]", is("self")))
    .andExpect(jsonPath("$.links[0].href[0]", is("/"));
person Akmal Rakhimov    schedule 14.04.2015
comment
Знаете ли вы, есть ли способ сделать это без жесткого кодирования индексов массива (в случае другого порядка)? - person Kevin M; 25.04.2017
comment
Кевин, вы можете использовать регулярное выражение в своем jsonpath, например, $.links[?(@.rel =~ /.*self/i)] или что-то в этом роде. Пожалуйста, ознакомьтесь с полной документацией здесь: github.com/json-path/JsonPath - person Akmal Rakhimov; 28.04.2017
comment
Этот подход не будет работать для HashSet, потому что порядок элементов не является детерминированным. - person Leonid Dashko; 12.05.2020

Принятый ответ мне кажется нормальным. Но я не знаком с junit4. Поэтому я добавлю сюда, как я буду тестировать типичный сценарий с использованием Junit5.

mockMvc.perform(get("/"))
    .andDo(print())
    .andExpect(status().isOk())
    .andExpect(jsonPath("$.links", hasSize(2)))
    .andExpect(jsonPath("$.links[0].rel[0]")
        .value("self"))
    .andExpect(jsonPath("$.links[0].href[0]")
        .value("/"))

Я добавлю здесь статический импорт (в случае новичка), потому что, когда я впервые работал, мне нужно было выяснить, какой импорт в нескольких импортах.

import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

Надеюсь, это будет полезно для кого-то. особенно кто-то новичок в модульном тестировании :)

person Menuka Ishan    schedule 16.01.2019

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

MockMvc.perform(get("/"))
.andDo(print()).andExpect(status().isOk())
.andExpect(jsonPath("$.links[*].rel").value(Matchers.containsInAnyOrder(Matchers.containsInAnyOrder(Matchers.is("self")))));
person Satrajit A    schedule 13.12.2020