Micronaut 和 JUnit 回滚

Posted

技术标签:

【中文标题】Micronaut 和 JUnit 回滚【英文标题】:Micronaut and JUnit rollback 【发布时间】:2020-04-27 00:01:58 【问题描述】:

我为 micronaut 微服务编写了一些测试。我希望在我的测试完成后,数据库中的所有更改都被还原(回滚)。首先,我写了一个似乎可行的简单示例。更改被还原。但是当我使用相同的类比运行微服务测试时,更改不会恢复。

简单的工作示例:

@Test
@Transactional
public void testRollback() 
    try (Connection connection = dataSource.getConnection();

        Statement stmt = connection.createStatement())
        connection.setAutoCommit(false);
        stmt.execute(String.format("INSERT INTO city VALUES (9999, 'Darko town', '123')"));
        connection.rollback();

     catch (SQLException e) 
        Assert.fail("Exception " + e);
    

执行此操作后,城市将从数据库中删除。

我的真实测试场景:

@Test
@Transactional
public void testDeleteDocuments() 

    try (final Connection connection = deletionService.getDataSource().getConnection(); 

        Statement stmt = connection.createStatement()) 
        connection.setAutoCommit(false);
        deletionService.startHacDeletion();
        connection.rollback();

    catch (SQLException e) 
        Assert.fail("Exception " + e);
    


通过我正在测试的方法完成的所有操作:DeletionService.startHacDeletion() 未还原。

我错过了什么吗?这是正确的方法吗?请帮忙....

更新:

这里是删除功能

public void deleteHacDocuments () 

    List<Document> allComments = new ArrayList<>();

    while (hacDeletionActive) 
        List<Document> parentDocuments = documentRepository.findHacDocuments();

        LOG.info(String.format("Remove HAC parent documents %d", parentDocuments.size()));

        for(Document document : parentDocuments)
            LOG.info(String.format("Remove HAC documents %d", document.getId()));
        


        if (parentDocuments.isEmpty()) 
            hacDeletionActive = false;
            LOG.info("HAC deletion finished");
         else 

            for (Document doc : parentDocuments) 
                if (doc.getType() == 1) 
                     deleteWholeStudy(doc.getId());
                 else if (doc.getType() == 6) 
                    List<Document> studies = documentRepository.findStudiesByCase(doc.getId());

                    for (Document study : studies) 
                        deleteWholeStudy(study.getId());
                    

                    deleteWholeCase(doc.getId());

                 else if (doc.getType() == 4) 
                    allComments.add(doc);
                 else 
                    documentService.markDocumentAsDeleted(doc.getId());
                
            
            documentService.markCommentsAsDeleted(allComments);
        



【问题讨论】:

在您解释 startHacDeletion 的作用之前,无法判断。 它做了很多事情。通过更改数据库中的某些字段来更改某些域类。 这么多东西可能是更改没有回滚的原因。在给出更多信息之前,无法确定。 检查问题的更新 您是否在使用 Truncate 或 drop 之类的查询? 【参考方案1】:

我对 Micronaut 框架不是很熟悉,也不太明白如果手动回滚更改,为什么需要 @Transactional 注释。

但是从您的示例中可以明显看出,在第一种情况下,您使用connection 创建一个用于执行查询的statement,然后在同一个connection 上调用回滚。 在第二种情况下,您从DataSource 获得connection,但您没有将它传递给服务以使用它,因此如果DataSource 使用某个连接池并且并不总是返回相同的连接,则服务将从它那里获得另一个connection,而不是你要回滚的那个。

这是我在您的代码中看到的唯一可能的问题,如果我的回答不能帮助解决您的问题,请提供a minimal, reproducible example。

【讨论】:

【参考方案2】:

Dbunit 是 JUnit 用于数据库测试的特殊扩展 http://dbunit.sourceforge.net/howto.html

JUnit 本身并不是为与数据库一起工作而设计的,因此,您遇到了这个问题并考虑了一个复杂的解决方案。

【讨论】:

【参考方案3】:

不完全相同的用例,因为我使用 Spock 进行测试,但我很确定 JUnit 中存在类似以下内容。

在每次将一些数据写入数据库的测试中,我所做的是执行一个cleanup 块,该块会删除所有创建的数据。 为了确保我们不会忘记删除测试中创建的所有内容并污染其他测试,我们有一个父 cleanup,它在每次测试后执行,并确保数据库中没有数据。基本上运行select count(*) from xxxxx,如果有数据则测试失败。

如前所述,这不是您问题的真正答案,而是您可以遵循的不同方法。它对我们来说非常有效。

【讨论】:

【参考方案4】:

根据您使用的测试库,您需要设置和拆除测试数据。 将 Datasource 注入到 Test 类中,并使用 datasource.connection 执行查询以清理数据。

【讨论】:

【参考方案5】:

@MicronautTest 注释你的休息类,它会默认进行回滚。摆脱你正在做的所有尝试/捕获连接的东西。您不需要显式回滚您的连接。在此处查看示例:https://github.com/micronaut-projects/micronaut-test/blob/master/test-junit5/src/test/java/io/micronaut/test/junit5/JpaRollbackTest.java

【讨论】:

我的课程使用@MicronautTest 进行了注释。似乎没有帮助....

以上是关于Micronaut 和 JUnit 回滚的主要内容,如果未能解决你的问题,请参考以下文章

git 代码回滚回退到指定版本 并 提交

git 代码回滚回退到指定版本 并 提交

111

junit测试事务回滚时遇到的问题

仅在 Asp.net 中回滚到特定迁移

Junit测试在事务后不回滚