在JUnit 4中,您可以使用规则来包装测试,以便您可以在测试运行之前和之后执行代码。在大多数情况下,这可以通过@Before和@After方法或ExternalResource规则来完成。但是,某些控制流构造(如try-with-resources)不能分为两种方法。在大多数情况下,这些构造的替代方法允许您将它们分成两种方法。例如,使用try-with-resources,您可以手动获取和关闭资源,而不是使用try块。
我遇到的具体问题是我使用的数据库库jOOQ只有采用回调的事务方法。 (见https://www.jooq.org/doc/latest/manual/sql-execution/transaction-management/)你不能称之为:
context.startTransaction()
doStuff()
context.commit() // Or rollback()
在JUnit4中,这是可以的,因为你可以像这样写一个规则(在Kotlin中,但是在Java中等效的工作):
class TransactionRule(private val dbSessionManager: DBSessionManager) : TestRule {
override fun apply(base: Statement, description: Description): Statement {
return object : Statement() {
override fun evaluate() {
dbSessionManager.transaction {
base.evaluate()
}
}
}
}
}
JUnit 5中有类似内容吗?
答案 0 :(得分:0)
根据我的理解,您无法使用JUnit 5 test lifecycle callbacks,因为它们会要求您通过doStuff
来电context
来电Before
来跟踪After
路径import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import org.junit.jupiter.api.function.Executable;
@TestFactory
Collection<DynamicTest> transactionTestCollection() {
return Arrays.asList(
dbTest("1st dynamic test", () -> assertTrue(true)),
dbTest("2nd dynamic test", () -> assertEquals(4, 2 * 2))
);
}
private DynamicTest dbTest(String name, Executable tst) {
return dynamicTest(name, () -> dbSessionManager.transaction(tst));
}
/ SELECT r.rom_ID
FROM rom r
WHERE r.rom_ID NOT LIKE(
SELECT r.rom_ID
FROM rom r, booking b
WHERE b.rom_ID = r.rom_ID
and (
'2018-05-08' BETWEEN b.ankomstdato AND b.utsjekkdato OR
'2018-05-12' BETWEEN b.ankomstdato AND b.utsjekkdato OR
('2018-05-08' <= b.ankomstdato AND '2018-05-12' >= b.utsjekkdato
) ) ) AND r.romtype_ID = 2
LIMIT 1;
你表明不会起作用。
使用JUnit 5 Dynamic Tests代替吗?
这为测试工厂提供了包含名称和可执行文件(lambda)的动态测试集合。然后你可以做这样的事情:
Control.BackColor
答案 1 :(得分:0)
您可以编写一个InvocationInterceptor来代替JUnit4规则:
public class TransactionInvocationInterceptor implements InvocationInterceptor {
@Override
public void interceptTestMethod(Invocation<Void> invocation,
ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable {
runInTransaction(() -> {
try {
invocation.proceed();
} catch (Throwable t) {
throw new RuntimeException(t);
}
});
}
}
@ExtendWith(TransactionInvocationInterceptor.class)
class InvocationInterceptorTest {
@Test
void test() {
…
}
}
一个区别是interceptTestMethod
仅包装测试方法,而不包装其他生命周期方法,例如beforeEach
。可以与InvocationInterceptor
中的其他方法分别拦截其他生命周期方法,但一次不能多个(例如,如果要在一个事务中同时调用beforeEach
和test方法)。