春季启动测试抛出JdbcException“找不到表”

时间:2019-03-28 14:17:25

标签: java spring-boot spring-boot-test

我有application-test.properties,其中定义了两个数据源

    app.datasource.server.url=jdbc:h2:mem:fooserver
    app.datasource.server.username=sa
    app.datasource.server.password=
    app.datasource.server.driverClassName=org.h2.Driver
    app.datasource.server.hikari.minimumIdle=5
    app.datasource.server.hikari.maximumPoolSize=50
    app.datasource.server.hikari.idleTimeout=50000
    app.datasource.server.hikari.maxLifetime=55000


    app.datasource.manager.url=jdbc:h2:mem:barmanager
    app.datasource.manager.username=sa
    app.datasource.manager.password=
    app.datasource.manager.driverClassName=org.h2.Driver
    app.datasource.manager.hikari.minimumIdle=5
    app.datasource.manager.hikari.maximumPoolSize=50
    app.datasource.manager.hikari.idleTimeout=50000
    app.datasource.manager.hikari.maxLifetime=55000


    # Hibernate ddl auto (create, create-drop, validate, update)
    spring.jpa.hibernate.ddl-auto=create-drop


    #logging
    logging.level.root=info
    logging.file=foobar-rest-test.log

    #required for SpringBootTest does not know why
    spring.main.allow-bean-definition-overriding=true
    spring.h2.console.enabled=true
    spring.h2.console.path=/h2-console

每个数据源都要求有可用的名为“ foo”的架构,这将由schema-fooserver.sql和schema-barmanager.sql在这些sql脚本的每个SQL脚本中创建。因此,我定义了一个dataSourceIntializer Bean,可以在其中定义要加载的schema-sql文件。

@Bean(name = "managerDataSourceInitializer")
public DataSourceInitializer dataSourceInitializer1(@Qualifier("managerDataSource") DataSource datasource) {
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
    resourceDatabasePopulator.addScript(new ClassPathResource("schema-barmanager.sql"));        

    DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
    dataSourceInitializer.setDataSource(datasource);
    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
    return dataSourceInitializer;
}



@Bean(name = "serverDataSourceInitializer")
public DataSourceInitializer dataSourceInitializer1(@Qualifier("serverDataSource") DataSource datasource) {
    ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
    resourceDatabasePopulator.addScript(new ClassPathResource("schema-fooserver.sql"));

    DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
    dataSourceInitializer.setDataSource(datasource);
    dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
    return dataSourceInitializer;
}

在测试开始期间,日志显示这些模式文件已被调用并执行。

    2019-03-28 15:04:34.252 DEBUG 3124 --- [main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [schema-fooserver.sql]
    2019-03-28 15:04:34.252 DEBUG 3124 --- [main] o.s.jdbc.datasource.init.ScriptUtils     : 0 returned as update count for SQL: CREATE SCHEMA IF NOT EXISTS FOO
    2019-03-28 15:04:34.252 DEBUG 3124 --- [main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [schema-fooserver.sql] in 0 ms.


    2019-03-28 15:04:34.252 DEBUG 3124 --- [main] o.s.jdbc.datasource.init.ScriptUtils     : Executing SQL script from class path resource [schema-barserver.sql]
    2019-03-28 15:04:34.252 DEBUG 3124 --- [main] o.s.jdbc.datasource.init.ScriptUtils     : 0 returned as update count for SQL: CREATE SCHEMA IF NOT EXISTS FOO
    2019-03-28 15:04:34.252 DEBUG 3124 --- [main] o.s.jdbc.datasource.init.ScriptUtils     : Executed SQL script from class path resource [schema-barserver.sql] in 0 ms.

现在,当我尝试执行测试用例时,它由于以下错误而失败:

    28 15:04:36.035 DEBUG 3124 --- [           main] org.hibernate.SQL                        : insert into foo.Account (uid, password_hash, login) values (null, ?, ?)
    Hibernate: insert into foo.Account (uid, password_hash, login) values (null, ?, ?)
    2019-03-28 15:04:36.036 DEBUG 3124 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : could not prepare statement [insert into foo.Account (uid, password_hash, login) values (null, ?, ?)]

    org.h2.jdbc.JdbcSQLException: Tabelle "ACCOUNT" nicht gefunden
    Table "ACCOUNT" not found; SQL statement:
    insert into foo.Account (uid, password_hash, login) values (null, ?, ?) [42102-197]
        at org.h2.message.DbException.getJdbcSQLException(DbException.java:357)

目前,我正在尝试在测试用例中创建一个UserAccount

这是定义的UerEntity

    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    @Entity
    @Table(name = "foo.Account")
    public class UserEntity {

        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "uid")
        private Long id;
        @Column(name = "login")
        private String username;
        @Column(name = "password_hash")
        private String password;
 ....

这是测试用例。在createUser方法期间调用before方法时,会发生错误。

    @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    @ActiveProfiles("test")
    @AutoConfigureMockMvc
    public class UserControllerTest {
        private static final Logger LOG = LoggerFactory.getLogger(UserControllerTest.class);

        @LocalServerPort
        private int port;
        TestRestTemplate restTemplate = new TestRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        @Autowired
        private WfcSpringRestApplication controller;

        @Autowired
        private UserRepository repository;

        @Autowired
        private MockMvc mvc;

        private AuthenticationToken authToken;

        @Before
        public void before() throws Exception {
            headers = new HttpHeaders();
            UserEntity user = createTestUser(TEST_ADMIN_USER, TEST_ADMIN_MD5_PW, UserRight.ADMIN);
            UserEntity userService = createTestUser(TEST_SERVICE_USER, TEST_ADMIN_MD5_PW, UserRight.SERVICE);
            getAuthenticationTokenForTestUser(user);

        }


        private UserEntity createTestUser(String username, String md5_password, UserRight right) {

            UserEntity ue = new UserEntity();
            ue.setUsername(username);
            ue.setPassword(md5_password);

            UserRole roleAdmin = new UserRole();
            roleAdmin.setRight(right);

            ue.getRoles().put(roleAdmin.getRight(), roleAdmin);

            repository.save(ue);

            return ue;
        }


        @Test
        public void contextLoads() {
            assertThat(controller).isNotNull();
        }

在错误消息中,有正确的表名“无法准备语句[插入foo.Account””,为什么会引发未找到表帐户的异常?

1 个答案:

答案 0 :(得分:0)

我遇到了类似的错误,我尝试了其他网站上提到的几乎所有解决方案,例如 DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1; DB_CLOSE_ON_EXIT=假;忽略情况=真

但对我没有任何作用。

对于 Spring Boot 2.4+,在 application.properties 中使用 spring.jpa.defer-datasource-initialization=true(此处提到 - https://stackoverflow.com/a/68086707/8219358

我意识到其他解决方案更合乎逻辑,但没有一个对我有用,而这确实有效。