添加Twilio依赖后JUnit JsonPath测试失败原因排查
问题:添加Twilio依赖后Spring MVC测试中JsonPath断言失效
问题背景
原本正常运行的Spring MVC登录接口测试,在引入Twilio SDK依赖后,JsonPath断言抛出PathNotFoundException,提示响应是java.lang.String而非JSON对象。相关代码与错误信息如下:
控制器代码
@PostMapping("/login") public ResponseEntity<Object> login( @RequestParam("email") String email, @RequestParam("password") String password) { CurrentUser user = userService.findUser(email, password); return new ResponseEntity<>(user.toDTO(), HttpStatus.OK); } public record UserDTO( String id, String firstName, String lastName ){}
测试代码
ResultActions response = mockMvc.perform(post("/users/login") .param("email", testEmail) .param("password", testPassword)); response .andExpect(status().isOk()) .andExpect(jsonPath("$.firstName").value(testUser.getFirstName()));
引入的Twilio依赖
<dependency> <groupId>com.twilio.sdk</groupId> <artifactId>twilio</artifactId> <version>10.1.3</version> </dependency>
报错信息
Caused by: com.jayway.jsonpath.PathNotFoundException: Expected to find an object with property ['firstName'] in path $ but found 'java.lang.String'. This is not a json object according to the JsonProvider: 'com.jayway.jsonpath.spi.json.JsonSmartJsonProvider'.
失效原因
问题根源是依赖冲突导致JSON解析器被替换:
- Spring Boot默认使用Jackson作为JSON处理库,
spring-boot-starter-test中的JsonPath默认依赖Jackson的解析实现。 - Twilio SDK的依赖树中包含
json-smart库,会被自动引入项目。 - JsonPath会自动选择classpath中优先级更高的JSON Provider,此时
JsonSmartJsonProvider取代了Jackson的实现。 JsonSmartJsonProvider无法正确识别Spring MVC返回的JSON对象,将其错误解析为普通字符串,导致JsonPath无法定位$.firstName路径。
解决方案
方案1:排除Twilio依赖中的json-smart
在Twilio依赖中显式排除json-smart,保留Spring Boot默认的Jackson解析:
<dependency> <groupId>com.twilio.sdk</groupId> <artifactId>twilio</artifactId> <version>10.1.3</version> <exclusions> <exclusion> <groupId>net.minidev</groupId> <artifactId>json-smart</artifactId> </exclusion> </exclusions> </dependency>
方案2:强制指定JsonPath使用Jackson Provider
在测试类中添加配置,指定JsonPath使用Jackson解析器:
import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.spi.json.JacksonJsonProvider; import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider; import java.util.EnumSet; import java.util.Set; @BeforeEach void setup() { Configuration.setDefaults(new Configuration.Defaults() { private final JsonProvider jsonProvider = new JacksonJsonProvider(); private final MappingProvider mappingProvider = new JacksonMappingProvider(); @Override public JsonProvider jsonProvider() { return jsonProvider; } @Override public MappingProvider mappingProvider() { return mappingProvider; } @Override public Set<Option> options() { return EnumSet.noneOf(Option.class); } }); }
补充说明
如果尝试排除spring-boot-starter-test中的json-path再单独引入Jackson依赖,会导致测试依赖缺失——spring-boot-starter-test的json-path已经整合了必要的测试支持,直接排除会破坏依赖链,不建议这么做。
内容的提问来源于stack exchange,提问作者DSG
相关产品推荐
相关产品推荐

