如何在 Kotlin 中使用单独的 profile/environment 数据源进行 Micronaut 测试?

How to use a separate profile/environment data source for Micronaut test in Kotlin?

我正在尝试为我用 Kotlin 编写的 Micronaut Web 应用程序使用两个数据源一个带有 mysql 数据库,以及执行测试时要使用的内存 H2 数据库中的一个 .

我试过只使用 h2 数据库作为默认的生产数据源,所以关于它的配置字段应该是正确的。

通过执行 ./gradlew run

,应用程序 运行 与 mysql 数据源符合预期
  1. 我试过将数据源放在单独的配置文件中,application.ymlapplication-test.yml 放在 src/main/resources/ 目录中,并且只将 application-test.yml 放在 src/test/resources/, 没有结果.
  2. 添加 @MicronautTest 注释声明 test 环境和 application = BookieSparaerverApplication 参数无效。
  3. BookieServerApplication 添加 @TypeHint(Genre::class, Book::class, DefaultGenreRepository::class) 注释无效。

这些是src/main/resources/application.yml配置文件的相关字段

datasources:
  default:
    url: 'jdbc:mysql://localhost:3306/bookie-server?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false'
    dbCreate: create-update
    driverClassName: com.mysql.cj.jdbc.Driver
    dialect: org.hibernate.dialect.MySQL5InnoDBDialect
    username: root
    password: root

jpa:
  default:
    entity-scan:
      packages:
        - 'com.transgressoft.bookieserver.domain'
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        show_sql: true

这是 src/test/resources/application-test.yml 文件:

datasources:
  default:
    url: ${JDBC_URL:`jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE`}
    username: ${JDBC_USER:sa}
    password: ${JDBC_PASSWORD:""}
    driverClassName: ${JDBC_DRIVER:org.h2.Driver}

jpa:
  default:
    entity-scan:
      packages:
        - 'com.transgressoft.bookieserver.domain'
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        show_sql: true

当我执行测试时(代码中的 GenreControllerSpec),看起来 EntityManager bean 没有被创建,因此 DAO class 无法被实例化(在我的代码中是GenreRepository class).

这是完整的日志消息:

Internal Server Error: Failed to inject value for parameter [entityManager] of class: com.transgressoft.bookieserver.domain.$DefaultGenreRepositoryDefinition$Intercepted

Message: No bean of type [javax.persistence.EntityManager] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
Path Taken: new $GenreControllerDefinition$Intercepted([GenreRepository genreRepository],BeanContext beanContext,Interceptor[] interceptors) --> new $DefaultGenreRepositoryDefinition$Intercepted([EntityManager entityManager],ConfigurationProperties applicationConfiguration,BeanContext beanContext,Interceptor[] interceptors)
io.micronaut.http.client.exceptions.HttpClientResponseException: Internal Server Error: Failed to inject value for parameter [entityManager] of class: com.transgressoft.bookieserver.domain.$DefaultGenreRepositoryDefinition$Intercepted

完整的项目代码可以在这里访问 https://github.com/octaviospain/bookie-server/tree/feature/jpa-and-hibernate 并重现上述日志只需执行 ./gradlew test 并打开报告,或者 运行 它激活日志。

编辑:我已经根据 Ivan Lopez 的建议更新了描述,但错误和预期结果保持不变。

我认为您误解了定义数据源的工作原理。 设置时:

datasources:
  production:
    ...

  test:
    ...

jpa:
  production:
    ...

  test:
    ...

您正在告诉 Micronaut:“我希望您创建 两个 数据源,一个名为 production,另一个名为 test 同时 。这两个数据源都将对应用程序可用,您可以使用定义的名称(productiontest)和限定符注入它们。

您需要做的是在src/main/resources/application.yml中只定义一个数据源。 Micronaut 使用 default 名称作为默认名称:

datasources:
  default:
    ... // your production MySQL database 

jpa:
  default:
    ... // configuration for MySQL database

然后您可以覆盖 application.yml 中定义的任何内容,只需使用以下内容创建 src/test/resources/application-test.yml

datasources:
  default:
    ... // your test H2 database 

jpa:
  default:
    ... // configuration for H2 database

希望它有意义。您可以在此处找到更多相关信息:https://docs.micronaut.io/latest/guide/index.html#config

您的示例应用程序使用 micronaut-hibernate-jpa 的 1.1.1,不支持

jpa:
  default:
    entity-scan:
      packages:
        - 'com.transgressoft.bookieserver.domain'

您必须使用 jpa.default.packages-to-scan 而不是 documentation 状态。