如何强制 `.andExpect(jsonPath()` 为 return Long/long 而不是 int 用于 jackson 解析器的 int 数字
How to force `.andExpect(jsonPath()` to return Long/long instead int for int number for jackson parser
我对 RestController 进行了简单测试。我希望 $[1].parent_id
returns Long 作为一个对象而不是整数基元。如果 parent_id
在长数字范围内并且 > 整数范围(例如:2147483650L),它将 return 长。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@WebAppConfiguration
public class TransactionServiceControllerTest {
@Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
// I copy this from my RestController class
this.transactions = Arrays.asList(
new Transaction(100d, "car", null),
new Transaction(100d, "table", 12L)
);
}
@Test
public void readSingleBookmark() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/transaction/"))
.andExpect(content().contentType(contentType)) // ok
.andExpect(jsonPath("$", hasSize(2))) // ok
//omitted
andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId())));
} //assertion fail
Expected: is <12L>
but: was <12>
另一项测试的结果:
Expected: is <12L>
but: was <2147483650L> //return Long instead int
这是我的 JacksonConfiguration
@Configuration
public class JacksonConfiguration {
@Bean
@Primary
public ObjectMapper objectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
//supposed to be this is the magic trick but it seems not..
objectMapper.enable(DeserializationFeature.USE_LONG_FOR_INTS);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return objectMapper;
}
}
还有我的 POJO
public class Transaction {
private double ammount;
private String type;
private Long parentId;
public Transaction(Double ammount, String type, Long parentId) {
//omitted
}
//setter and getter omitted
}
MyRestController
@RestController
@RequestMapping("transaction")
public class TransactionServiceController {
@RequestMapping(method = RequestMethod.GET)
List<Transaction> getTransaction() {
return
Arrays.asList(
new Transaction(100d, "car", null),
new Transaction(100d, "table", 12L)
);
}
}
和Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class,args);
}
}
更新
- Spring Framework 4.3.3 和 5.0.0 首先添加-class 支持显式转换 request 内容以用于
MockRestServiceServer
.
- 详情见SPR-14498。
- Spring Framework 4.3.15 和 5.0.5 将添加 first-class 对 response 内容的显式转换支持,以便与 [=12] 一起使用=].
- 详情见SPR-16587。
原答案
一个选择(我还没有亲自验证)是尝试不同的 JsonProvider
。这可以通过 com.jayway.jsonpath.Configuration.setDefaults(Defaults)
.
设置
如果您确定 Long
始终可以安全地缩小为 int
,您可以使用以下内容:
andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId().intValue())));
唯一的其他选择是编写自定义 Matcher
,在执行实际匹配之前将传入的 Integer
转换为 Long
。
从 Spring 5.2 开始,您可以提供类型作为 jsonPath()
方法的第三个参数:
public static <T> ResultMatcher jsonPath(String expression, Matcher<T> matcher, Class<T> targetType)
所以在这种情况下它将是:
andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId()), Long.class));
我对 RestController 进行了简单测试。我希望 $[1].parent_id
returns Long 作为一个对象而不是整数基元。如果 parent_id
在长数字范围内并且 > 整数范围(例如:2147483650L),它将 return 长。
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@WebAppConfiguration
public class TransactionServiceControllerTest {
@Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
// I copy this from my RestController class
this.transactions = Arrays.asList(
new Transaction(100d, "car", null),
new Transaction(100d, "table", 12L)
);
}
@Test
public void readSingleBookmark() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/transaction/"))
.andExpect(content().contentType(contentType)) // ok
.andExpect(jsonPath("$", hasSize(2))) // ok
//omitted
andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId())));
} //assertion fail
Expected: is <12L>
but: was <12>
另一项测试的结果:
Expected: is <12L>
but: was <2147483650L> //return Long instead int
这是我的 JacksonConfiguration
@Configuration
public class JacksonConfiguration {
@Bean
@Primary
public ObjectMapper objectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
//supposed to be this is the magic trick but it seems not..
objectMapper.enable(DeserializationFeature.USE_LONG_FOR_INTS);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT);
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return objectMapper;
}
}
还有我的 POJO
public class Transaction {
private double ammount;
private String type;
private Long parentId;
public Transaction(Double ammount, String type, Long parentId) {
//omitted
}
//setter and getter omitted
}
MyRestController
@RestController
@RequestMapping("transaction")
public class TransactionServiceController {
@RequestMapping(method = RequestMethod.GET)
List<Transaction> getTransaction() {
return
Arrays.asList(
new Transaction(100d, "car", null),
new Transaction(100d, "table", 12L)
);
}
}
和Application.java
@SpringBootApplication
public class Application {
public static void main(String[] args){
SpringApplication.run(Application.class,args);
}
}
更新
- Spring Framework 4.3.3 和 5.0.0 首先添加-class 支持显式转换 request 内容以用于
MockRestServiceServer
.- 详情见SPR-14498。
- Spring Framework 4.3.15 和 5.0.5 将添加 first-class 对 response 内容的显式转换支持,以便与 [=12] 一起使用=].
- 详情见SPR-16587。
原答案
一个选择(我还没有亲自验证)是尝试不同的 JsonProvider
。这可以通过 com.jayway.jsonpath.Configuration.setDefaults(Defaults)
.
如果您确定 Long
始终可以安全地缩小为 int
,您可以使用以下内容:
andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId().intValue())));
唯一的其他选择是编写自定义 Matcher
,在执行实际匹配之前将传入的 Integer
转换为 Long
。
从 Spring 5.2 开始,您可以提供类型作为 jsonPath()
方法的第三个参数:
public static <T> ResultMatcher jsonPath(String expression, Matcher<T> matcher, Class<T> targetType)
所以在这种情况下它将是:
andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId()), Long.class));