如何在使用testcontainers进行集成测试时管理EM或EMF?

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

我有java web应用程序,我想编写服务层的集成测试。我决定使用testcontainers,所以在测试中我想调用service,它将与docker容器中的数据库一起使用。

我的测试类看起来像下面的示例。

@Testcontainers
class ITPlayerServiceImpl {

  @Container
  private static final PostgreSQLContainer POSTGRE_SQL_CONTAINER = 
  new PostgreSQLContainer()
            .withDatabaseName("dbName")
            .withUsername("dbUserName")
            .withPassword("dbPassword");
}

经过测试的服务。

@Stateless
public class PlayerServiceImpl implements PlayerService {

  @PersistenceContext(unitName = "persistence_unit_name")
  private EntityManager entityManager;

  //Methods

我需要在容器中创建连接到DB的EMF,然后将EM从该EMF填充到测试服务中。

感谢您的帮助或提示。

java integration-testing entitymanager testcontainers
1个回答
0
投票

经过一些调查和测试后,我结束了以下解决方案。

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@Testcontainers
class ITApplicationUserService {

    @Container
    private static final PostgreSQLContainer POSTGRE_SQL_CONTAINER = new PostgreSQLContainer()
            .withDatabaseName("someDatabase")
            .withUsername("someUsername")
            .withPassword("somePassword");

    // EMF for integration tests
    private static EntityManagerFactory emf;

    // EM for tested service
    private static EntityManager entityManager;

    // Tested service
    private static ApplicationUserServiceImpl applicationUserService = new ApplicationUserServiceImpl();

    // Object used for testing
    private static ApplicationUser testingApplicationUser;


    @BeforeAll
    static void init() {

        // Properties for our EMF, which will make EM connected to POSTGRE_SQL_CONTAINER
        Map<String,String> properties = new HashMap<>();
        properties.put("javax.persistence.jdbc.url",POSTGRE_SQL_CONTAINER.getJdbcUrl());
        properties.put("javax.persistence.jdbc.user",POSTGRE_SQL_CONTAINER.getUsername());
        properties.put("javax.persistence.jdbc.password",POSTGRE_SQL_CONTAINER.getPassword());
        properties.put("javax.persistence.jdbc.driver",POSTGRE_SQL_CONTAINER.getDriverClassName());
        properties.put("eclipselink.logging.level","FINE");

        // We need create fresh empty schema in POSTGRE_SQL_CONTAINER
        properties.put("javax.persistence.schema-generation.database.action","create");

        // Creation of EMF
        emf = Persistence.createEntityManagerFactory("integrationTesting",properties);

        // Player for testing
        testingApplicationUser = new ApplicationUser();
        testingApplicationUser.setLogin("loginName");
        testingApplicationUser.setEmail("[email protected]");
        testingApplicationUser.setPassword("123456");
    }

    @Test
    @Order(1)
    void saveNewApplicationUserTest() {
        assertTrue(testingApplicationUser.getId()==null);
        ApplicationUser applicationUser = applicationUserService.saveApplicationUser(testingApplicationUser);
        assertTrue(applicationUser.getId()!=null);
    }

    @Test
    @Order(2)
    void getApplicationUsers() {
        assertTrue(applicationUserService.getAllApplicationUsers().size()==1);
    }


    @BeforeEach
    private void startTransaction() throws IllegalAccessException, NoSuchFieldException {
        entityManager = emf.createEntityManager();
        // We will declare field of EM in tested service
        // EM field in tested class is not public and should not be. We will use reflection for population of EM.
        Field emField = applicationUserService.getClass().getDeclaredField("entityManager");
        emField.setAccessible(true);
        emField.set(applicationUserService,entityManager);

        entityManager.getTransaction().begin();
    }

    @AfterEach
    private void commitTransaction() {
        if (entityManager.getTransaction().isActive()) {
            entityManager.getTransaction().commit();
            entityManager.close();
        }

    }

}
© www.soinside.com 2019 - 2024. All rights reserved.