使用 MockServer 的 Wiremock 返回模拟的 http 响应时尝试更新嵌入式数据库
Posted
技术标签:
【中文标题】使用 MockServer 的 Wiremock 返回模拟的 http 响应时尝试更新嵌入式数据库【英文标题】:Trying to update embedded database when mocked http response is returned using Wiremock of MockServer 【发布时间】:2021-09-09 01:08:43 【问题描述】:在 Spring Boot 上下文中工作,我正在测试一个查询数据库的服务,然后进行远程调用以更新数据库,然后重新查询数据库以获取更新的数据。
我正在尝试使用 Wiremock 或 MockServer 来模拟远程调用,但不知道如何在模拟服务器响应生成过程中更新嵌入式数据库。
例如,使用 MockServer,我尝试创建一个具有自动装配 JdbcTemplate 实例的回调类,但在回调的上下文中 JdbcTemplate 变量为空。
public class ApprovalHappyPathCallback implements ExpectationResponseCallback
JdbcTemplate jdbcTemplate;
@Autowired
public void setDataSource(DataSource ds)
jdbcTemplate = new JdbcTemplate(ds);
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();
回调执行,但 jdbcTemplate 语句不起作用。
在测试中回调是这样引用的:
mockServer.when(request().withMethod("GET"))
.withBody("Approved")
// );
.respond(
callback()
.withCallbackClass(ApprovalHappyPathCallback.class)
);
进行远程调用的服务方法本质上是:
public CommunicationEntity approveCommunication(Long communicationId)
String approvalToken = commRepo.approvalTokenById(communicationId);
if (approvalToken == null)
approvalToken = UUID.randomUUID().toString();
communicationEntity.setApprovalToken(approvalToken);
commRepo.save(communicationEntity);
String approvalResponse = remoteCommunicationApprover.approveCommunication(communicationId, approvalToken);
CommunicationEntity communicationEntity = getCommunicationById(communicationId);
if (communicationEntity.getStatus() != CommunicationStatus.Approved_Scheduled)
throw new BadRequestException(
"Approval request for communication " + communicationId + " and token " + approvalToken
+ " failed with remote response: " + approvalResponse,
ErrorCodes.COMMUNICATION_SVC_REMOTE_APPROVAL_REQUEST_FAILED);
return communicationEntity;
【问题讨论】:
ApprovalHappyPathCallback
是 Spring 托管的 Bean 吗?
【参考方案1】:
有两个问题导致问题:确保回调方法中使用的 jdbcTemplate 配置了正确的 DataSource,并确保嵌入式内存数据库中的数据可以从 MockServer 响应生成线程访问。
我通过对 MockServer 回调使用 lambda 或闭包解决了第一个问题,其中我使用在测试类中创建的 JdbcTemplate 实例和自动装配的 DataSource(尽管回调类方法也存在解决方案)。
第二个问题是测试方法在事务中的结果,因此当 MockServer 线程(请注意,MockServer 响应生成发生在与运行测试方法的主线程不同的线程)正在执行回调。因此,回调无法访问这些插入。
解决方案是使用 @Transactional(propagation = Propagation.NOT_SUPPORTED) 注释测试方法 见h2 database access to test data from separate threads
【讨论】:
以上是关于使用 MockServer 的 Wiremock 返回模拟的 http 响应时尝试更新嵌入式数据库的主要内容,如果未能解决你的问题,请参考以下文章