在尝试使用MockMvcResultMatchers从Spring REST服务测试JSON输出时遇到问题,其中返回的对象应包含Long值。
仅当JSON对象中的值大于Integer.MAX_VALUE时,测试才会通过。我觉得这有点奇怪,因为我认为我应该能够测试所有适用值。
我知道,由于JSON不包含类型信息,因此它在反序列化时会对类型进行最佳猜测,但是我希望在MockMvcResultMatchers中执行比较时,有一种方法可以强制类型提取。
完整代码在下面,但测试在:
@Test
public void testGetObjectWithLong() throws Exception {
Long id = 45l;
ObjectWithLong objWithLong = new ObjectWithLong(id);
Mockito.when(service.getObjectWithLong(String.valueOf(id))).thenReturn(objWithLong);
mockMvc.perform(MockMvcRequestBuilders.get("/Test/" + id))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue")
.value(Matchers.isA(Long.class)))
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue")
.value(Matchers.equalTo(id)));
}
结果是:
java.lang.AssertionError: JSON path$longvalue
Expected: is an instance of java.lang.Long
but: <45> is a java.lang.Integer
at org.springframework.test.util.MatcherAssertionErrors.assertThat(MatcherAssertionErrors.java:80)
...
任何有关解决此问题的正确方法的想法或建议,将不胜感激。显然,我可以将Integer.MAX_VALUE添加到测试中的id字段中,但这似乎很脆弱。
提前致谢。
除第三方库外,以下内容应自成体系
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RunWith(MockitoJUnitRunner.class)
public class TestControllerTest {
private MockMvc mockMvc;
@Mock
private RandomService service;
@InjectMocks
private TestController controller = new TestController();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controller)
.setMessageConverters(new MappingJackson2HttpMessageConverter())
.build();
}
@Test
public void testGetObjectWithLong() throws Exception {
Long id = 45l;
ObjectWithLong objWithLong = new ObjectWithLong(id);
Mockito.when(service.getObjectWithLong(String.valueOf(id))).thenReturn(objWithLong);
mockMvc.perform(MockMvcRequestBuilders.get("/Test/" + id))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue").value(Matchers.isA(Long.class)))
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue").value(Matchers.equalTo(id)));
}
@RestController
@RequestMapping(value = "/Test")
private class TestController {
@Autowired
private RandomService service;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ObjectWithLong getObjectWithLong(@PathVariable final String id) {
return service.getObjectWithLong(id);
}
}
@Service
private class RandomService {
public ObjectWithLong getObjectWithLong(String id) {
return new ObjectWithLong(Long.valueOf(id));
}
}
private class ObjectWithLong {
private Long longvalue;
public ObjectWithLong(final Long theValue) {
this.longvalue = theValue;
}
public Long getLongvalue() {
return longvalue;
}
public void setLongvalue(Long longvalue) {
this.longvalue = longvalue;
}
}
}
您可以将anyOf Matcher与针对Number超类的Class匹配一起使用,并将其设置为
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue")
.value(Matchers.isA(Number.class)))
.andExpect(MockMvcResultMatchers.jsonPath("$longvalue")
.value(Matchers.anyOf(
Matchers.equalTo((Number) id),
Matchers.equalTo((Number) id.intValue()))));
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句