У меня есть простой контроллер, который запрашивает число у некоторой случайной службы REST и упаковывает ее в объект JSON.Эти числа могут быть целыми числами или числами с плавающей точкой.Таким образом, потребители моей конечной точки REST должны ожидать значение с плавающей запятой.
Это мой контроллер:
import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
public class NumberController {
private final RestTemplate restTemplate;
@Autowired
public NumberController(final RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@RequestMapping(path = "/number", method = GET, produces = APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public String getNumber() {
final String number = restTemplate.getForObject("https://example.com/number", String.class);
return String.format("{\"number\":%s}", number);
}
}
Теперь я хочу проверить, действительно ли конечная точка возвращает число, которое вызывает RESTвозвращается.Поэтому я написал тест, который использует MockMvc
:
import static org.hamcrest.Matchers.is;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.client.RestTemplate;
@SpringBootTest
@SpringJUnitWebConfig
@AutoConfigureMockMvc
class NumberControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private RestTemplate restTemplate;
@ParameterizedTest
@MethodSource("createTestData")
void testNumbersEndpoint(final String restServiceValue, final double expectedValue) throws Exception {
given(restTemplate.getForObject(any(String.class), eq(String.class))).willReturn(restServiceValue);
mockMvc.perform(get("/number"))
.andExpect(status().isOk())
.andExpect(jsonPath("number", is(expectedValue)));
}
private static Stream<Arguments> createTestData() {
return Stream.of(Arguments.of("17", 17.0), Arguments.of("12.53", 12.53));
}
}
Таким образом, конечная точка может либо вернуть { "number": 17 }
, либо { "number": 12.53 }
, что является допустимым значением JSON.С .andExpect(jsonPath("number", is(expectedValue)))
я проверяю, действительно ли структура JSON содержит число, которое было возвращено удаленной службой REST.К сожалению, тест не пройден для { "number": 17 }
, потому что jsonPath("number", ...)
передает целочисленное значение целочисленному методу.
Итак, как мне сопоставить оба целочисленных значения с плавающей запятой?
Я думал о чем-товроде следующего, но это не работает:
@ParameterizedTest
@MethodSource("createTestData")
void testNumbersEndpoint(final String restServiceValue, final Number expectedValue) throws Exception {
given(restTemplate.getForObject(any(String.class), eq(String.class))).willReturn(restServiceValue);
mockMvc.perform(get("/number"))
.andExpect(status().isOk())
.andExpect(jsonPath("number", is(expectedValue)));
}
private static Stream<Arguments> createTestData() {
return Stream.of(Arguments.of("17", BigDecimal.valueOf(17)), Arguments.of("12.53", BigDecimal.valueOf(12.53)));
}