@DataJpaTest 和 @SpringBootTest 查询 src/main/resources 数据库而不是 src/test/resources 数据库

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

我正在努力彻底理解 Spring Boot,尤其是测试。

我希望所有测试都针对 src/test/resources 内的 application.properties 中的数据库运行,无论活动配置文件如何。但由于某种原因它只查询 src/main/resources 数据库。

我现在创建了以下配置文件(也许这些名称没有意义):

  • tdd
  • 舞台
  • 生产

我通过脚本文件创建了两个具有相同架构和功能的数据库:

  • 神话学习
  • 神话学习测试

我在 src/test/resources/db/Data.sql 中还有一个单独的 Data.sql 文件

我有一个正在运行的本地 Postgres 数据库,因为我使用的是 Postgres,所以我觉得不需要任何测试容器或 H2,我只是在同一实例上创建了另一个数据库以进行本地测试,这是可以接受的吗?

据我所知,src/test/resources 中的所有内容都应该用于测试,但不知何故,所有测试都针对活动配置文件中的任何数据库运行。

由于某种原因,所有@DataJpaTests和@SpringBootTests都在src/test/resources/db/Data.sql中查找Data.sql脚本, 但由于某种原因,它正在针对 src/main/resources 文件内的活动配置文件中定义的数据库运行测试。

我只添加了我认为对于这个问题必要的代码,但我会很乐意编辑它并提供更多细节。

这是代码:

SQL

TRUNCATE serverappsplayground.DummyEntity RESTART IDENTITY CASCADE ;
INSERT INTO serverappsplayground.DummyEntity (name, key, value, x, y, z)
VALUES
('DE-Name 1', 'key-1', 'value-1', 65, 33, FLOOR(RANDOM() * 1000)),
('DE-Name 2', 'key-2', 'value-2', 47, 96, FLOOR(RANDOM() * 1000)),
('DE-Name 3', 'key-3', 'value-3', 22, 34, FLOOR(RANDOM() * 1000)),
('DE-Name 4', 'key-4', 'value-4', 77, 56, FLOOR(RANDOM() * 1000)),
('DE-Name 5', 'key-5', 'value-5', 89, 17, FLOOR(RANDOM() * 1000)),
('DE-Name 6', 'key-6', 'value-1', 4, 78, FLOOR(RANDOM() * 1000)),
('DE-Name 7', 'key-7', 'value-2', 13, 8, FLOOR(RANDOM() * 1000)),
('DE-Name 8', 'key-8', 'value-8', 67, 10, FLOOR(RANDOM() * 1000)),
('DE-Name 9', 'key-9', 'value-9', 56, 2, FLOOR(RANDOM() * 1000)),
('DE-Name 10', 'key-10', 'value-10', 99, 43, FLOOR(RANDOM() * 1000)),
('DE-Name 11', 'key-11', 'value-11', 65, 33, FLOOR(RANDOM() * 1000)),
('DE-Name 12', 'key-12', 'value-12', 47, 96, FLOOR(RANDOM() * 1000)),
('DE-Name 13', 'key-13', 'value-13', 22, 34, FLOOR(RANDOM() * 1000)),
('DE-Name 14', 'key-14', 'value-14', 77, 56, FLOOR(RANDOM() * 1000)),
('DE-Name 15', 'key-15', 'value-15', 89, 17, FLOOR(RANDOM() * 1000)),
('DE-Name 16', 'key-16', 'value-16', 4, 78, FLOOR(RANDOM() * 1000)),
('DE-Name 17', 'key-17', 'value-17', 13, 8, FLOOR(RANDOM() * 1000)),
('DE-Name 18', 'key-18', 'value-18', 67, 10, FLOOR(RANDOM() * 1000)),
('DE-Name 19', 'key-19', 'value-19', 56, 2, FLOOR(RANDOM() * 1000)),
('DE-Name 20', 'key-20', 'value-20', 99, 43, FLOOR(RANDOM() * 1000));

配置:

应用程序.yml

spring:

    # Set the application name and description:
    application:
      name: "SpringBootWebMvcJavaFoundation"
      description: "This is the fundamental foundation project for Spring Boot"
    main:
      keep-alive: true

  # Setting the profile
    profiles.active: stage

    # Enabling virtual threads
    # This is extremely important in order to maximise performance and make the most of Java 21
    threads.virtual.enabled: true

    # Data access layer

    jpa:
      hibernate:
        # This property is extremely important as I want to remove Spring Boot making queries with those underscores by default:
        naming.physical-strategy: "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl"

        # Here we make sure Spring Data JPA does not mess around with my database as I don't want it too,
        # It makes sure there are no ddl statements in any profile
        ddl-auto: none

    test:
      database:
        replace: none

应用程序-tdd.yml:

spring:
  sql:
    init:
      mode: always
      # Adding the classpath prefix to all paths,
      # and then following the path as normal works for tests + when app context is loaded
      # Note: Schema generation does not  need to happen everytime, I can also manually load the schema,
      # This makes tests slow, so I must simply aware, anytime changes are made too Schema or functions,
      # Either uncomment this to be safe or remember and manually modify the schema with psql,

      #schema-locations: classpath:db/Schema.sql,classpath:db/Functions.sql
      data-locations: classpath:db/Data.sql
  datasource:
    url: jdbc:postgresql://localhost:5432/MythicalLearnTest
  jpa:
    show-sql: 'true'
testpropertyexists: 'yes'

应用程序阶段.yml

spring:
  sql:
    init:
      mode: always
      #schema-locations: classpath:db/Schema.sql,classpath:db/Functions.sql
      #data-locations: classpath:db/Data.sql
  datasource:
    url: "jdbc:postgresql://localhost:5432/MythicalLearn"

src/test/resources 中的application.properties:

spring.sql.init.mode=always
spring.datasource.url=jdbc:postgresql://localhost:5432/MythicalLearnTest
spring.sql.init.data-locations=classpath:db/Data.sql

测试代码

@DataJpaTest基类:

@org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class DataJpaTest {
    
}

class DummyJpaServiceDbTest extends DataJpaTest {

    private DummyJpaService dummyJpaService;

    @Autowired
    private DummyJpaRepo dummyJpaRepo;

    @BeforeEach
    void setUp() {
        dummyJpaService = new DummyJpaService(dummyJpaRepo);
    }

    @Test
    void works() {
        assertTrue(true);
    }

    @Test
    void getAllDummies() {
        assertEquals(
                20,
                dummyJpaService.getAllDummies().size()
        );
    }

    @Test
    void getDummyById() {
        assertEquals(
                "key-7",
                dummyJpaService.getDummyById(7).get().getKey()
        );
    }

    @Test
    void createDummy() {
        DummyEntity entity = new DummyEntity();
        entity.setKey("key-222");
        dummyJpaService.createDummy(entity);
        assertEquals(21, dummyJpaService.getAllDummies().size());
    }

    @Test
    void updateDummy() {
        DummyEntity entity = dummyJpaService.getDummyById(7).get();
        entity.setName("UPDATED DE7");
        dummyJpaService.updateDummy(entity);
        assertEquals("UPDATED DE7", dummyJpaService.getDummyById(7).get().getName());
    }

    @Test
    void deleteDummy() {

        DummyEntity entity = dummyJpaService.getDummyById(20).get();
        dummyJpaService.deleteDummy(entity);
        assertEquals(19, dummyJpaService.getAllDummies().size());
    }

    @Test
    void deleteDummyById() {
        DummyEntity entity = dummyJpaService.getDummyById(20).get();
        dummyJpaService.deleteDummyById(entity.getId());
        assertEquals(19, dummyJpaService.getAllDummies().size());
    }
}

@SpringBootTest

@SpringBootTest
@AutoConfigureMockMvc
@Sql(scripts = "classpath:db/Data.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public class SpringBootJavaApplicationTests {

    @Test
    void contextLoads() {
    }

}

    class DummyApiServiceIntegrationTest extends SpringBootJavaApplicationTests {

    @Autowired
    private MockMvc mvc;

    private String basePath = "/dummy-entity-api";

    @Autowired
    private ObjectMapper mapper;

    @BeforeEach
    void setUp() {

    }

    @Test
    @DisplayName("Checking and hoping the real database is loaded for tests")
    void getAllDummies() throws Exception {
        MvcResult result = mvc.perform(
            get(basePath + "/dummies")
        ).andReturn();

        assertThat(result.getResponse().getContentAsString()).isNotBlank();

    }

    @Test
    @DisplayName("Testing the response returns the 20 lists that are in the dummy data")
    void getAllDummiesObjects() throws Exception {
        MvcResult result = mvc.perform(
            get(basePath + "/dummies")
        ).andReturn();

        //Use the arrrays.asList because mapper returns an array:
        List<DummyEntity> dummyEntityList = getDummyListFromJson(
            result.getResponse().getContentAsString()
        );

        assertThat(dummyEntityList.size()).isEqualTo(20);
    }

    @Test
    @DisplayName("When id not found then we get 404")
    void getByIdNotFound() throws Exception {
        mvc.perform(
            get(basePath + "/{25}", 25)

        ).andExpect(status().isNotFound());
    }

    @Test
    @DisplayName("When id found then it is 200")
    void getByIdFound() throws Exception {
        mvc.perform(
            get(basePath + "/{1}", 1)

        ).andExpect(status().isOk());
    }

    @Test
    @DisplayName("Testing that it creates a new entity")
    void testCreates() throws Exception {
        DummyEntity dummyEntity = new DummyEntity();
        dummyEntity.setName("DE-Created By Spring Boot test");
        dummyEntity.setKey("key-21");
        dummyEntity.setValue("value-21");
        dummyEntity.setXYZ(1,2,3);

        MvcResult result = mvc.perform(
                post(basePath + "/create")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(mapper.writeValueAsString(dummyEntity))
            )
            .andReturn();

        assertThat(result.getResponse().getStatus()).isEqualTo(201);

    }

    @Test
    @DisplayName("Here i am testing that the extra entity is added, but then on each load it is reset")
    void testExtraEnttityIsAdded() throws Exception {
        DummyEntity dummyEntity = new DummyEntity();
        dummyEntity.setName("DE-Created By Spring Boot test");
        dummyEntity.setKey("key-21");
        dummyEntity.setValue("value-21");
        dummyEntity.setXYZ(1,2,3);

        mvc.perform(
                post(basePath + "/create")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(mapper.writeValueAsString(dummyEntity))
            )
            .andReturn();

        //Not a very readable expression, but later I can learn
        assertThat(
            getDummyListFromJson(
                mvc.perform(
                        get(basePath + "/dummies")
                    )
                    .andReturn()
                    .getResponse()
                    .getContentAsString()
            ).size()
        ).isEqualTo(21);



        //Getting the list so I can see it should be 21:

    }

    /**
     * Keeping a private function that gets a List from JSON String,
     * So I do not have to repeat myself multiple times:
     */
    private List<DummyEntity> getDummyListFromJson(String jsonList) throws Exception {
        return Arrays.asList(
            mapper.readValue(
                jsonList,
                DummyEntity[].class
            )
        );
    }



}

现在,我有两个独立的数据库,但是当我在暂存配置文件中运行测试时,它会在 test/resources 中找到 Data.sql 脚本,但由于某种原因,不会针对测试数据库运行测试:

我已经多次截断表格,同样的事情发生了

如何让所有测试仅针对测试数据库运行,而不管配置文件如何? 这可能吗? 或者也许,我想做的事情很愚蠢,并且有更好的工作流程?

我忍不住想,这是一件非常简单的事情,甚至没有提到,但我不明白。 我将不胜感激任何建议

postgresql spring-boot spring-data-jpa tdd spring-boot-configuration
1个回答
0
投票

现在发生的情况是,两个文件(

src/test/resources/application.properties
src/main/resources/application.yml
)中的密钥已合并,因此
spring.profiles.active
密钥出现在您的测试中。

将您的

src/test/resources/application.properties
重命名为
src/test/resources/application.yml
。这将覆盖
src/main/resources/application.yml
。所以现在只有来自
src/test/resources/application.yml
的键才会出现在测试中。

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