【发布时间】:2018-10-27 14:13:54
【问题描述】:
我有一个简单的控制器,它从一些随机 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)));
}
【问题讨论】:
标签: java spring-mvc spring-boot spring-boot-test spring-mvc-test