31

目前 JUnit 5 API 只允许@BeforeAll使用静态方法。

所以如果我做这样的事情,它不会编译:

@BeforeAll
  fun setup() {
    MockitoAnnotations.initMocks(this)
    mvc = MockMvcBuilders.standaloneSetup(controller).build()
}

为了在 Kotlin 中有一个静态方法,我必须companion object像这样使用:

companion object {
    @JvmStatic
    @BeforeAll
    fun setup() {
      MockitoAnnotations.initMocks(this)
      mvc = MockMvcBuilders.standaloneSetup(smsController).build()
    }
}

这将编译,但我无权访问父类中的变量。那么@BeforeAll用 Kotlin 调用 JUnit 5 的惯用方式是什么?

4

5 回答 5

30

JUnit 5 具有@TestInstance(PER_CLASS)可用于此目的的注释。它启用的功能之一是非静态BeforeAllAfterAll方法:

@TestInstance(PER_CLASS)
class BeforeAllTests {

    lateinit var isInit = false

    @BeforeAll
    fun setup() {
        isInit = true
    }

   @TestFactory
   fun beforeAll() = listOf(
       should("initialize isInit in BeforeAll") {
           assertTrue(isInit)
       }
   )
}

fun should(name: String, test: () -> Unit) = DynamicTest.dynamicTest("should $name", test)
于 2018-02-16T06:45:01.367 回答
8

如文档中所述@BeforeAll

表示被注解的方法应该在当前类中的所有@Test方法之前执行;类似于 JUnit 4 的 @BeforeClass。此类方法必须是静态的并且可以继承。

以上对于 Kotlin 和 Java 都是正确的。请记住,默认情况下,Junit 将为每个测试用例创建一个单独的测试类实例。仅适用于静态方法是有道理的,@BeforeAll因为它应该在当前测试用例的任何代码之前被调用。静态方法无法访问实例成员,因为它可以在没有实例的情况下调用。

如 Spring 文档中所述:

另一方面,“standaloneSetup”更接近于单元测试。

该示例表明您应该像这样使用实例成员:

class StandaloneTest {
  val smsController = ... // create instance of controller
  val MockMvcBuilders.standaloneSetup(smcController).build()
}

的用处@BeforeAll是有限的,通常应该避免,因为它可能会鼓励测试用例之间的运行时依赖。

于 2016-07-22T06:04:52.743 回答
6

您可以访问伴随对象中的变量:

    companion object {

        private lateinit var objectToBeInitialized: Test

        @BeforeAll
        @JvmStatic
        fun setup() {
            objectToBeInitialized = Test()
        }
    }
于 2020-09-17T10:50:00.180 回答
3

JUnit 5 supports test extensions, for example BeforeAllCallback

import org.junit.jupiter.api.extension.BeforeAllCallback
import org.junit.jupiter.api.extension.ExtensionContext

class BeforeAllTests : BeforeAllCallback {
    override fun beforeAll(context: ExtensionContext?) {
        System.out.println("Before all executed");
    }
}

In your Kotlin test class

@ExtendWith(BeforeAllTests::class)
class MyAppCoreTest : MyAppTest() {

    @Test
    fun someTest() { }
}
于 2018-06-29T14:41:17.180 回答
-1

在 a@SpringBootTest中,这是一个简单的解决方案。注意@BeforeAllfun 可以使用 Spring 注入的属性。

@SpringBootTest(classes = [Application::class])
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {

    @Autowired
    lateinit var someBean: SomeBean

    lateinit var propertyForAll: PropertyForAll

    @BeforeAll
    fun setup() {
        propertyForAll = PropertyForAll(someBean.valueXyz())
    }

    @Test
    fun `First test`() {
        val something = propertyForAll.findSomething("Banana")
        // test continues
    }

    @Test
    fun `Second test`() {
        val something = propertyForAll.findSomething("Orange")
        // test continues
    }
}

值得一看:

于 2020-08-03T17:47:44.333 回答