如何强制`.andExpect(jsonPath()`返回Long/long而不是int for int number for jackson parser

sla*_*ata 11 json spring-test jackson spring-rest

我对我的RestController进行了简单的测试.我希望$[1].parent_id返回Long作为对象而不是整数原语.如果parent_id在长数字范围和>整数范围内(例如:2147483650L),它将返回Long .

@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>
Run Code Online (Sandbox Code Playgroud)

另一项测试的结果:

Expected: is <12L>
but: was <2147483650L> //return Long instead int
Run Code Online (Sandbox Code Playgroud)

这是我的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

还有我的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
}
Run Code Online (Sandbox Code Playgroud)

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)
            );
    }
}
Run Code Online (Sandbox Code Playgroud)

和Application.java

@SpringBootApplication
public class Application {
    public static void main(String[] args){
        SpringApplication.run(Application.class,args);
    }
}
Run Code Online (Sandbox Code Playgroud)

Sam*_*nen 10

更新

  • Spring Framework 4.3.3和5.0.0 为使用的请求内容添加了对显式转换的一流支持MockRestServiceServer.
  • Spring Framework 4.3.15和5.0.5将为响应内容的显式转换添加一流支持以供使用MockMvc.

原始答案

一个选项(我尚未亲自验证)将尝试不同的选择JsonProvider.这可以通过设置com.jayway.jsonpath.Configuration.setDefaults(Defaults).

如果您确定Long始终可以安全地缩小到a int,则可以使用以下内容:

andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId().intValue())));
Run Code Online (Sandbox Code Playgroud)

唯一的另一种选择是编写一个自定义项Matcher,在执行实际匹配之前将传入转换Integer为a Long.


小智 10

从 Spring 5.2 开始,您可以提供 type 作为jsonPath()方法的第三个参数:

public static <T> ResultMatcher jsonPath(String expression, Matcher<T> matcher, Class<T> targetType)
Run Code Online (Sandbox Code Playgroud)

所以在这种情况下,它将是:

andExpect(jsonPath("$[1].parent_id",is(this.transactions.get(1).getParentId()), Long.class));
Run Code Online (Sandbox Code Playgroud)

来源: Spring Javadoc API