如何测试使用@Resource注入的数据源

问题描述

我想为以下课程创建一些集成测试:

public class MyDao {
    @Inject
    @Postgres
    private DataSource dataSource;

    getSomething() {
        //do something with dataSource
    }
}

我有资格赛:

@Qualifier
@Target({ TYPE,METHOD,FIELD,ParaMETER })
@Retention(RUNTIME)
public @interface Postgres {
}

还有一个制片人:

public class PostgresDataSourceProducer {

    @Resource(mappedname = "java:jboss/PostgresDS")
    private DataSource ds;

    @Produces
    @Postgres
    DataSource postgresDataSouce() {
        return ds;
    }
}

我正在使用wildfly14。数据源是在standalone.xml中定义的:

<subsystem xmlns="urn:jboss:domain:datasources:5.0">
        <datasources>
            <datasource jta="false" jndi-name="java:jboss/PostgresDS" pool-name="postgres" enabled="true" use-ccm="false">
                <connection-url>jdbc:postgresql://${production.postgres.url}</connection-url>
                <driver-class>org.postgresql.Driver</driver-class>
                <driver>postgresql-8.0-310.jdbc3.jar</driver>
                <security>
                    <user-name>${db.username}</user-name>
                    <password>${db.userpass}</password>
                </security>
                <validation>
                    <validate-on-match>false</validate-on-match>
                    <background-validation>false</background-validation>
                </validation>
                <statement>
                    <share-prepared-statements>false</share-prepared-statements>
                </statement>
            </datasource>
        </datasources>
</subsystem>

要创建集成测试,我将需要更改数据源以指向我的测试数据库。该怎么做?

由于这是一个代码,我保留从@Resource切换到@PersistenceContext的权限。

解决方法

有许多方法可以做到这一点,但首先,在子系统中定义测试数据源(为便于使用,请在下面的示例中使用java:jboss/H2对其进行映射)。

通过CDI @Alternative

为测试数据源创建另一个生产者类,并将其标记为替代类。

示例:

public class PostgresDataSourceProducer {

    @Resource(mappedName = "java:jboss/PostgresDS")
    private DataSource primary;

}

@Alternative
public class H2DataSourceProducer {

    @Resource(mappedName = "java:jboss/H2")
    private DataSource test;

}

在测试资源目录中,添加一个专门用于测试的新CDI描述符文件。您可能需要从主描述符文件中复制配置,以保留行为或避免运行时错误。

示例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       version="1.1" bean-discovery-mode="all">
    <alternatives>
         <class>path.to.your.datasource.H2DataSourceProducer</class>
    </alternatives>
</beans>

最后,当通过Shrinkwrap创建测试工件时,将受影响的模块的CDI描述符文件替换为上面的模块。

示例:

final var services = ...;
services.addAsManifestResource("META-INF/beans.xml","beans.xml");

通过JPA持久性单元配置

您还可以只删除数据源生产者,并让JPA在运行时通过持久性单元配置获取正确的数据源。

在测试资源目录中添加新的persistence.xml文件。保留除数据源属性以外的所有主要持久性配置。

示例:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">
    <persistence-unit name="primary">
        
        <!--<jta-data-source>java:jboss/PostgresDS</jta-data-source>-->
        <jta-data-source>java:jboss/H2</jta-data-source>
        ...
    </persistence-unit>
</persistence>

最后,当通过Shrinkwrap创建测试工件时,将主持久性配置文件替换为上面的文件。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...