首页 > 解决方案 > 用于测试的 Spring Security Oauth2 H2 - 未找到表“OAUTH_ACCESS_TOKEN”

问题描述

这里我使用 InMemoryTokenStore。通过执行以下操作,我可以让这个 TokenStore 在运行应用程序时工作:

@Configuration
public class AppConfig {

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    // ...
}

现在我可以向 /oauth/token 发出 HTTP 请求并获取访问令牌。我还可以访问授权资源。而且,我的测试甚至可以在运行中通过并创建表(例如 oauth_access_token 表)。

但是,我不想将 InMemoryTokenStore 用于开发和以后的生产环境。所以,我试图在测试属性文件中使用配置 H2 仅用于我的测试,我打算使用 MySQL 的其他环境。

所以我修改了我的配置类:

@Configuration
public class AppConfig {

    @Value("${spring.datasource.url}")
    private String datasourceUrl;

    @Value("${spring.datasource.username}")
    private String dbUsername;

    @Value("${spring.datasource.password}")
    private String dbPassword;

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(datasourceUrl);
        dataSource.setUsername(dbUsername);
        dataSource.setPassword(dbPassword);
        return dataSource;
    }

    @Bean
    public TokenStore tokenStore(DataSource dataSource) {
        return new JdbcTokenStore(dataSource);
    }

    // ...
}

每个环境我都有两个 application.properties 文件:

src/main/resources/application.properties

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:33067/budget?useSSL=false
spring.datasource.username=budget
spring.datasource.password=s3cret

src/test/resources/application.properties

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

我的意图是测试环境将使用 H2 db 配置,而其他环境将使用 MySQL db 配置。但是,我现在在测试中看到以下错误:

2019-12-30 21:09:41.627 ERROR 20628 --- [           main] o.s.s.o.provider.endpoint.TokenEndpoint  : Handling error: BadSqlGrammarException, PreparedStatementCallback; bad SQL grammar [select token_id, token from oauth_access_token where authentication_id = ?]; nested exception is org.h2.jdbc.JdbcSQLException: Table "OAUTH_ACCESS_TOKEN" not found; SQL statement:
select token_id, token from oauth_access_token where authentication_id = ? [42102-197]

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select token_id, token from oauth_access_token where authentication_id = ?]; nested exception is org.h2.jdbc.JdbcSQLException: Table "OAUTH_ACCESS_TOKEN" not found; SQL statement:
select token_id, token from oauth_access_token where authentication_id = ? [42102-197]
        at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:234) ~[spring-jdbc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) ~[spring-jdbc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
        at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1402) ~[spring-jdbc-5.0.9.RELEASE.jar:5.0.9.RELEASE]
...

我可以确认测试正在获取 H2 配置,但由于表丢失而引发错误。如果我跳过测试,那么我可以运行应用程序并成功发出 HTTP 请求 - 如果 MySQL 数据库中缺少表,它会创建它。InMemoryTokenStore 配置也会创建表,因此不会发生此错误 - 但我不希望这用于开发/产品。但是测试期间的 H2 配置(src/test/resources/application.properties)会由于表丢失而引发错误,因此它没有创建任何看起来的表。我究竟做错了什么?

标签: spring-booth2spring-security-oauth2

解决方案


推荐阅读