Spring Boot测试中用Wiremock/MockServer返回响应时更新嵌入式数据库
问题原因
你使用withCallbackClass注册回调时,MockServer会通过无参构造自行反射创建回调类实例,该实例不受Spring上下文管理,@Autowired注解不会生效,因此jdbcTemplate为null。MockServer默认会吞噬回调方法抛出的异常,因此你只会观察到更新语句不生效,不会收到空指针报错。
解决方案
方案1:传入Spring托管的回调实例(推荐)
- 将回调类改为Spring组件,通过构造函数注入依赖
@Component public class ApprovalHappyPathCallback implements ExpectationResponseCallback { private final JdbcTemplate jdbcTemplate; public ApprovalHappyPathCallback(DataSource dataSource) { this.jdbcTemplate = new JdbcTemplate(dataSource); } public static final HttpResponse httpResponse = response() .withStatusCode(HttpStatusCode.ACCEPTED_202.code()) .withHeaders( header("x-callback", "test_callback_header"), header("Content-Length", "a_callback_response".getBytes(UTF_8).length), header("Connection", "keep-alive") ) .withBody("a_callback_response"); @Override public HttpResponse handle(HttpRequest httpRequest) { if (httpRequest.getMethod().equals("GET")) { jdbcTemplate.execute("update communications set status = 'APPROVED_SCHEDULED' where id = 153511"); return httpResponse; } else { return notFoundResponse(); } } }
- 在测试类中注入该回调实例,注册时使用
withCallbackObject代替withCallbackClass
@Autowired private ApprovalHappyPathCallback approvalHappyPathCallback; // 注册Mock规则 mockServer.when(request().withMethod("GET")) .withBody("Approved") .respond( callback() .withCallbackObject(approvalHappyPathCallback) );
方案2:直接在测试类内编写回调逻辑(更轻量)
无需单独创建回调类,直接在测试类中使用注入的JdbcTemplate编写回调:
@Autowired private JdbcTemplate jdbcTemplate; // 注册Mock规则 mockServer.when(request().withMethod("GET").withBody("Approved")) .respond(httpRequest -> { if ("GET".equals(httpRequest.getMethod())) { jdbcTemplate.execute("update communications set status = 'APPROVED_SCHEDULED' where id = 153511"); return response() .withStatusCode(HttpStatusCode.ACCEPTED_202.code()) .withHeaders( header("x-callback", "test_callback_header"), header("Content-Length", "a_callback_response".getBytes(StandardCharsets.UTF_8).length), header("Connection", "keep-alive") ) .withBody("a_callback_response"); } return notFoundResponse(); });
注意事项
- 若测试用例添加了
@Transactional注解,默认会在测试结束后回滚所有数据库操作,回调执行的更新也会被回滚,符合单测隔离要求 - 不建议写死数据库记录ID,可通过ThreadLocal存储测试用例生成的动态ID,在回调中读取使用,提升测试用例通用性
内容的提问来源于stack exchange,提问作者David Lewine
相关产品推荐
相关产品推荐

