Skip to content

Instantly share code, notes, and snippets.

@bastman
Last active June 4, 2023 21:25
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bastman/248c7022d699f2bcbfba25ca358e66aa to your computer and use it in GitHub Desktop.
Save bastman/248c7022d699f2bcbfba25ca358e66aa to your computer and use it in GitHub Desktop.
junit5: Testfactory DSL (kotlin) - dynamic, nested tests ...
package com.example
import com.example.testutils.junit5.testFactory
import com.example.testutils.springTest.BootWebMockMvcTest
import mu.KLogging
import org.amshove.kluent.shouldEqual
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestFactory
import org.springframework.beans.factory.annotation.Autowired
import java.math.BigDecimal
internal class ExchangeRateRepoTest(
@Autowired private val repo: SomeRepo
) : BootWebMockMvcTest() {
companion object : KLogging()
@Test
fun `test sth`() {
1 shouldEqual 1
}
@TestFactory
fun `test sth else`() = testFactory {
test("a test") { 1 shouldEqual 1 }
container("foo") {
test("bar") { 1 shouldEqual 1 }
test("baz") { 1 shouldEqual 1 }
}
container("foo2") {
container("another container") {
test("bar") { 1 shouldEqual 1 }
test("baz") { 1 shouldEqual 1 }
}
test("baz") { 1 shouldEqual 1 }
}
test("another test") { 1 shouldEqual 1 }
}
}
package com.example.testutils.junit5
import org.junit.jupiter.api.DynamicContainer
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.function.Executable
import java.util.stream.Stream
class TestContainerBuilder(private var name: String) : TestProvider, ContainerProvider {
private val nodes: MutableList<DynamicNode> = mutableListOf()
fun name(value: String) {
name = value
}
fun name(): String = name
override fun test(name: String, test: () -> Any?) {
val node = dynamicTest(name, test)
nodes.add(node)
}
override fun container(name: String, init: TestContainerBuilder.() -> Unit) {
val node = containerBuilder(name = name, init = init)
nodes.add(node)
}
operator fun invoke(): DynamicContainer = build()
private fun build(): DynamicContainer = dynamicContainer(name, nodes.toList())
}
private fun containerBuilder(name: String, init: TestContainerBuilder.() -> Unit): DynamicContainer {
return TestContainerBuilder(name = name)
.apply(init)()
}
class TestFactoryBuilder : TestProvider, ContainerProvider {
private val nodes: MutableList<DynamicNode> = mutableListOf()
override fun test(name: String, test: () -> Any?) {
val node = dynamicTest(name, test)
nodes.add(node)
}
override fun container(name: String, init: TestContainerBuilder.() -> Unit) {
val node = containerBuilder(name = name, init = init)
nodes.add(node)
}
operator fun invoke(): Stream<out DynamicNode> = nodes.stream()
}
fun testFactory(init: TestFactoryBuilder.() -> Unit): Stream<out DynamicNode> = TestFactoryBuilder()
.apply(init)()
private interface TestProvider {
fun test(name: String, test: () -> Any?)
}
private interface ContainerProvider {
fun container(name: String, init: TestContainerBuilder.() -> Unit)
}
private fun dynamicContainer(name: String, nodes: List<DynamicNode>): DynamicContainer =
DynamicContainer.dynamicContainer(name, nodes)
private fun dynamicTest(name: String, test: () -> Any?): DynamicTest =
DynamicTest.dynamicTest(name, executable(test))
private fun executable(test: () -> Any?): Executable =
Executable {
test.invoke()
Unit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment