升级Play 2.8后Scala集成测试中无法注入JPA API的问题
在Play 2.8中DBUnit辅助类获取JPAApi的正确方式
核心原因
Play 2.8彻底移除了Play.current()静态方法,不再支持通过静态方式获取Injector,必须使用依赖注入的方式获取JPAApi,这是Play框架转向无状态、依赖注入优先架构的必然要求。
解决方案分两种场景
场景1:辅助类属于应用代码(被其他注入类调用)
直接通过构造注入获取JPAApi,让Guice管理辅助类的实例:
import play.db.jpa.JPAApi; import javax.inject.Inject; import javax.persistence.EntityManager; public class DbUnitHelper { private final JPAApi jpaApi; // 构造函数注入JPAApi,Guice会自动解析依赖 @Inject public DbUnitHelper(JPAApi jpaApi) { this.jpaApi = jpaApi; } public void executeDbUnitOperations() { jpaApi.withTransaction((EntityManager em) -> { // 这里执行你的DBUnit查询/数据集操作 return null; }); } }
使用这个辅助类时,同样通过注入获取实例,不要直接new DbUnitHelper(),比如在控制器或服务类中:
@Inject private DbUnitHelper dbUnitHelper;
场景2:辅助类用于测试环境(单元/集成测试)
如果是在测试中使用DBUnit,推荐借助Play的测试工具类管理应用上下文,从而获取正确的Injector:
方式A:使用Play的WithApplication测试基类
import org.junit.Test; import play.db.jpa.JPAApi; import play.test.WithApplication; import javax.persistence.EntityManager; public class DbUnitIntegrationTest extends WithApplication { @Test public void testDbDataSetSetup() { // 从测试应用实例中获取Injector JPAApi jpaApi = app.injector().instanceOf(JPAApi.class); jpaApi.withTransaction(em -> { // 执行DBUnit数据集初始化、验证操作 return null; }); } }
方式B:手动构建Guice Injector(独立测试工具类)
如果需要在脱离Play测试基类的情况下使用,需要手动加载Play的JPA模块并配置数据库参数:
import com.google.inject.Injector; import play.db.jpa.JPAApi; import play.inject.guice.GuiceInjectorBuilder; public class StandaloneDbUnitHelper { private final JPAApi jpaApi; public StandaloneDbUnitHelper() { // 构建Injector,加载Play JPA模块并配置数据库 Injector injector = new GuiceInjectorBuilder() .configure("db.default.driver", "com.mysql.cj.jdbc.Driver") .configure("db.default.url", "jdbc:mysql://localhost:3306/test_db") .configure("db.default.username", "root") .configure("db.default.password", "password") .configure("jpa.default.persistenceUnit", "defaultPersistenceUnit") .build(); this.jpaApi = injector.instanceOf(JPAApi.class); } // 后续DBUnit操作... }
常见注入失败原因排查
如果之前尝试Guice注入失败,大概率是以下问题:
- 直接
new了辅助类实例,没有通过Injector获取(Guice无法管理手动创建的实例,自然不会注入依赖) - 测试环境中没有加载Play的JPA模块,导致JPAApi的绑定不存在
- 数据库配置缺失,JPA模块无法初始化JPAApi实例
内容的提问来源于stack exchange,提问作者Andr Santos
相关产品推荐
相关产品推荐

