我希望此类
UserMapperTest.java
运行回滚事务的测试(在本例中是一个简单的插入,其中字段电子邮件是唯一的,但问题的核心是关于回滚):
import jakarta.inject.Inject;
import org.jboss.weld.junit5.WeldInitiator;
import org.jboss.weld.junit5.WeldJunit5Extension;
import org.jboss.weld.junit5.WeldSetup;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mybatis.cdi.Transactional;
import java.math.BigInteger;
@ExtendWith(WeldJunit5Extension.class)
@TestMethodOrder(MethodOrderer.MethodName.class)
@Transactional(rollbackOnly = true)
public class UserMapperTest {
@WeldSetup
WeldInitiator weldInitiator = WeldInitiator.of(WeldInitiator.createWeld().enableDiscovery());
@Inject
@TestSessionFactory
public UserMapper userMapper;
@Test
public void t1_insert_user() throws Exception {
User u = userMapper.selectUserFromId(BigInteger.ONE);
u.setId(null);
u.setEmail(u.getEmail() + "2");
userMapper.insertUser(u);
Assertions.assertNotNull(u);
Assertions.assertNotNull(u.getId());
}
}
对于此测试有用的主要
pom.xml
依赖项是:
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.weld/weld-junit5 -->
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-junit5</artifactId>
<version>${weld.junit5.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.weld.se/weld-se-core -->
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se-core</artifactId>
<version>${weld-se.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/jakarta.platform/jakarta.jakartaee-api -->
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>${jakartaee-api.version}</version>
<scope>provided</scope>
</dependency>
有了这些
versions
:
<junit.version>5.11.0-M2</junit.version>
<weld.junit5.version>4.0.3.Final</weld.junit5.version>
<weld-se.version>6.0.0.Beta4</weld-se.version>
<jakartaee-api.version>11.0.0-M4</jakartaee-api.version>
我的
bean.xml
是这样的:
<?xml version="1.0"?>
<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"
bean-discovery-mode="all">
<interceptors>
<class>org.mybatis.cdi.LocalTransactionInterceptor</class>
</interceptors>
</beans>
这是
TestSessionFactory
注释:
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import jakarta.inject.Qualifier;
@Qualifier
@Retention(RUNTIME)
@Target({ TYPE, METHOD, FIELD, PARAMETER })
public @interface TestSessionFactory {
}
这是
SqlSessionFactoryProvider
的SqlSessionFactoryProviderTest测试实现:
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.cdi.SessionFactoryProvider;
public class SqlSessionFactoryProviderTest implements SqlSessionFactoryProvider {
@Override
@TestSessionFactory
@Produces
@ApplicationScoped
@SessionFactoryProvider
public SqlSessionFactory produceFactory() {
return ConnectionFactory.getSqlSessionFactory();
}
}
我曾经在 javax 和 junit 4 中使用类似的代码并且工作得很好。我正在尝试升级到 jakarta 和 junit 5。我可能缺少 WeldInitiator 上的某些内容。
userMapper
已正确注入,查询也正确运行,只是事务未回滚。
在 Weld 的 JUnit 5 扩展中,测试类不是 CDI bean,因此
@Transactional
或应用于测试类的任何其他拦截器将不起作用。这是因为在创建扩展时,由于 JUnit API,这是不可能的。有一些 Weld-JUnit GH 问题对此进行了详细说明,例如 this one。
JUnit 此后添加了许多 API,其中包括一个提供测试实例的 API,但这一更改将破坏至少一些使用
WeldInitiator
的现有测试的兼容性,因为提供实例对测试本身设置了一些期望。话虽这么说,我并不反对实施这一点;我只是缺乏时间。
作为您的场景的解决方法,您必须将拦截的方法登录移动到另一个可以照常拦截的测试 bean 中。