如何包装JUnit 5测试

时间:2018-05-04 04:28:45

标签: junit junit5

在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中有类似内容吗?

2 个答案:

答案 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方法)。