JUnit4具有TestSuite
类来聚合多个测试。 这在JUnit 5中不可用。通常,通过套件中的一堆命名测试进行的测试发现有些糟透了。 但是,如果目标不是测试发现,而是不同测试类之间的资源共享,那么创建父对象是有意义的。
JUnit 5提供了@Nested
批注,以允许子类在其父类的上下文中运行。 假定子类是非静态的,因此可以访问其父类的实例值。 如果要共享测试资源,则可能需要考虑测试套件的类级别设置,并以某种方式将其连接到子类的类级别设置中。
让我们设计一个伪造的例子来说明问题:
@Testcontainers // use docker images @Testcontainers // use docker images class MyTest { // make a DB at the start of the test in a docker container // takes a few minutes to boot up @Container private static final DatabaseContainer DB = createDbContainer(); private static MyDao dao; @BeforeAll static void beforeAll() { dao = createDaoFrom(DB); } @Test void daoFeatureOne() { assertThat(dao.find( "no data" )).isEmpty(); } }
上面是一个测试,它在测试类的全局生命周期中启动数据库。 它将一个dao
对象连接到它,并且可以有多个测试可以重用该dao
。
在理想情况下,我们可以为每个测试重置所有内容,但是数据库是启动的昂贵资源。 也许我们可以添加一些beforeEach
和afterEach
挂钩来清理其数据,但是我们不想对数据库进行退回。 每一次。 类似地,如果每次运行,我们的dao
一些框架启动成本可能是不希望的。
上面作为我们项目中的唯一测试是可以的,但是如果还有其他需要该数据库的测试又该怎么办呢?如果真的需要运行AGES呢?
JUnit 5中没有套件
是不是很烦 如果我们可以做的话:
@JUnit5TestSuite // not real @Children ({MyDaoTest. class , MyOtherDaoTest. class }) @Testcontainers class MyTestSuite { @Container private static final DatabaseContainer DB = createDbContainer(); }
那将是很棒的……但是这会给我们带来一些问题:
- 我们如何确保子测试不在套件之外运行?
- 这些测试如何访问`DB`对象?
套房的替代选择
假设我们有一个静态方法getDb
在需要时提供数据库。
现在,让我们重写原始的DaoTest以使用它,并使其抽象化,以便测试运行器不会将其拾取:
abstract class MyTestImpl implements DbProvider { private static MyDao dao; @BeforeAll static void beforeAll() { // access to the database container // from the static method (statically imported) dao = createDaoFrom(getDb()); } @Test void daoFeatureOne() { assertThat(dao.find( "no data" )).isEmpty(); } }
现在我们可以在套件中运行部分测试,让我们定义套件。 我们还使用@Nested
来插入子类:
@Testcontainers // use docker images @Testcontainers // use docker images class MyTest { // make a DB at the start of the test in a docker container // takes a few minutes to boot up @Container private static final DatabaseContainer DB = createDbContainer(); // provide the getDb function to access the container public static DatabaseContainer getDb() { return DB; } // test suite members are just nested classes that extend // the abstract class of each member of the suite @Nested class MyTest extends MyTestImpl { } // ... add more suite members with more @Nested }
缺点
由于类在彼此的静态位上运行,因此存在产生混淆的风险。
每个嵌套类都必须是子类的事实也有点时髦……
但这有效并且构成了有效的测试套件。
翻译自: https://www.javacodegeeks.com/2020/04/junit5-testsuite-alternative.html