使用 MockServer 的 Wiremock 返回模拟 http 响应时尝试更新嵌入式数据库

Trying to update embedded database when mocked http response is returned using Wiremock of MockServer

在 Spring 引导上下文中工作,我正在测试查询数据库的服务,然后进行远程调用以更新数据库,然后重新查询数据库以获取更新的数据。

我正在尝试使用 Wiremock 或 MockServer 来模拟远程调用,但无法弄清楚如何在模拟服务器响应生成过程中更新嵌入式数据库。

例如,使用 MockServer,我尝试创建一个具有自动装配的 JdbcTemplate 实例的回调 class,但在回调的上下文中 JdbcTemplate 变量为 null。

    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;


有两个问题导致了问题:确保回调方法中使用的 jdbcTemplate 配置了正确的 DataSource,以及确保 MockServer 响应生成线程可以访问嵌入式内存 DB 中的数据。

我通过对 MockServer 回调使用 lambda 或闭包解决了第一个问题,其中我使用在测试 class 中创建的 JdbcTemplate 实例和自动装配的数据源(尽管存在回调 class 方法也是如此)。

第二个问题是由于测试方法在一个事务中,因此当 MockServer 线程时,测试开始时对数据库的插入没有提交(注意 MockServer 响应生成发生在与测试方法 运行) 正在执行回调的主线程不同的线程中。因此回调无法访问这些插入。

解决方案是用@Transactional(propagation = Propagation.NOT_SUPPORTED) 注释测试方法 参见