JUnit - 无 Spring Boot - 每次测试之间清理 H2 数据库

问题描述 投票:0回答:1

我在为 JUnit 设置 H2 数据库时遇到问题。 需要注意的是 - 我没有使用 Spring Boot 自动配置。

我想清除每次测试之间的所有数据。 测试类扩展了用于设置 H2 连接的 H2DatabaseConfig 类。 我的计划是使用 @AfterAll 注释清除所有数据。 我不想使用deleteAll方法,比如完全删除数据(行和自动增量重置)。

此刻, 当我单独运行每个测试时,一切都很好。 但是当我一起运行时,我收到错误

jakarta.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.example.database.entity.Team]

我知道它与我的父类有关。 它与我重新创建会话/连接的方式有关。 但不知道如何解决。

我很感激您提供的任何提示。先谢谢你了

H2数据库配置

public class H2DatabaseConfig {
    private static Server server;
    private static Connection connection;
    protected static EntityManagerFactory entityManagerFactory;
    private static EntityManager entityManager;
    @BeforeEach
    public void setUp() throws SQLException {
        server = Server.createTcpServer().start();
        connection = DriverManager.getConnection("jdbc:h2:mem:test;MODE=MYSQL", "root", "password");

        entityManagerFactory = Persistence.createEntityManagerFactory("entity-manager-test");
        entityManager = entityManagerFactory.createEntityManager();
        Container.initBeans(entityManager);
    }

    @AfterEach
    public void tearDown() throws SQLException {
        connection.close();
        server.stop();
    }
}

测试类

class FormTeamAddControllerTest extends H2DatabaseConfig {

    private FormTeamAddController formTeamAddController;
    private TeamSavePort teamSavePort;

    @BeforeEach
    public void set() {
        formTeamAddController = new FormTeamAddController();
        teamSavePort = Container.getBean(TeamSavePort.class);
    }
    @Test
    public void shouldSaveTeam() {
        // when
        ValidatorResponse save = formTeamAddController.save("Lowe", "123");

        // then
        assertTrue(save.isOk());
        assertEquals(TeamInputValidator.msgTeamIsCreated("Lowe"), save.getMessage());
    }

    @Test
    public void shouldNotSaveTeamCauseDuplicateTeamName() {
        teamSavePort.save("Star", BigDecimal.valueOf(123));
        // when
        ValidatorResponse save = formTeamAddController.save("Star", "123");

        // then
        assertTrue(save.hasErrors());
        assertEquals(save.getErrors().get("name"), TeamInputValidator.errTeamNameExists());
    }

    @Test
    public void shouldNotSaveTeamCauseWrongName() {
        // when
        ValidatorResponse save1 = formTeamAddController.save(null, "123");
        ValidatorResponse save2 = formTeamAddController.save("  ", "123");
        ValidatorResponse save3 = formTeamAddController.save("", "123");

        // then
        assertTrue(save1.hasErrors());
        assertTrue(save2.hasErrors());
        assertTrue(save3.hasErrors());

        assertEquals(save1.getErrors().get("name"), TeamInputValidator.errTeamName());
        assertEquals(save2.getErrors().get("name"), TeamInputValidator.errTeamName());
        assertEquals(save3.getErrors().get("name"), TeamInputValidator.errTeamName());
    }

    @Test
    public void shouldNotSaveTeamCauseWrongMembershipFee() {
        // when
        ValidatorResponse save1 = formTeamAddController.save("Star", null);
        ValidatorResponse save2 = formTeamAddController.save("Star", "   ");
        ValidatorResponse save3 = formTeamAddController.save("Star", "");

        // then
        assertTrue(save1.hasErrors());
        assertTrue(save2.hasErrors());
        assertTrue(save3.hasErrors());

        assertEquals(TeamInputValidator.errTeamFee(), save1.getErrors().get("membershipPayment"));
        assertEquals(TeamInputValidator.errTeamFee(), save2.getErrors().get("membershipPayment"));
        assertEquals(TeamInputValidator.errTeamFee(), save3.getErrors().get("membershipPayment"));
    }

}

持久性.xml

    <persistence-unit name="entity-manager-test" transaction-type="RESOURCE_LOCAL">
        <class>com.example.database.entity.Team</class>

        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS test" />
            <property name="jakarta.persistence.jdbc.user"   value="root" />
            <property name="jakarta.persistence.jdbc.password" value="password" />

            <!-- Generate the database schema -->
            <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>

            <!-- Customize the schema generation behavior -->
            <property name="javax.persistence.schema-generation.create-source" value="metadata"/>
            <property name="javax.persistence.schema-generation.drop-source" value="metadata"/>
            <property name="javax.persistence.schema-generation.scripts.action" value="none"/>


        </properties>
    </persistence-unit>
java junit h2
1个回答
0
投票

我认为您可以使用

@AfterEach
注释而不是
@AfterAll
来确保在每次单独测试后执行清理,因此在
H2DatabaseConfig
类中更改
@AfterEach
如下所示:

@AfterEach
public void tearDown() throws SQLException {
    entityManager.clear(); //clear entities from the session
    connection.close();
    server.stop();
}

并编辑

persistence.xml
文件以包含带有“drop-and-create”的
javax.persistence.schema-generation.database.action
属性,以删除并重新创建每个测试的数据库架构,并在运行测试之前确保干净的状态,如下所示:

<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
© www.soinside.com 2019 - 2024. All rights reserved.