<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.0.2</version> <scope>test</scope> </dependency>
import org.junit.jupiter.api.Test class HelloJunit5Test { @Test fun `First test`() { print("Hello, JUnit5!") } }
@DisplayName
, as well as in the name of the Kotlin function, in addition to the readable display name of the test, you can specify special characters and emoji: import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test class HelloJunit5Test { @DisplayName("\uD83D\uDC4D") @Test fun `First test ╯°□°)╯`() { print("Hello, JUnit5!") } }
@DisplayName("Override class name") class HelloJunit5Test {
org.junit.jupiter.Assertions
and are static methods.Supplier
functional interface, which allows to calculate the value of the string only in the case of a failed test: import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test class HelloJunit5Test { @Test fun `Base assertions`() { assertEquals("a", "a") assertEquals(2, 1 + 1, "Optional message") assertEquals(2, 1 + 1, { "Assertion message " + "can be lazily evaluated" }) } }
Person
class with two properties: class Person(val firstName: String, val lastName: String)
import org.junit.jupiter.api.Assertions.assertAll import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.junit.jupiter.api.function.Executable class HelloJunit5Test { @Test fun `Grouped assertions`() { val person = Person("John", "Doe") assertAll("person", Executable { assertEquals("John", person.firstName) }, Executable { assertEquals("Doe", person.lastName) } ) } }
@Test fun `Test assertTrue with reference and lambda`() { val list = listOf("") assertTrue(list::isNotEmpty) assertTrue { !list.contains("a") } }
@Test fun `Test exception`() { val exception: Exception = assertThrows(IllegalArgumentException::class.java, { throw IllegalArgumentException("exception message") }) assertEquals("exception message", exception.message) }
@Test fun `Timeout not exceeded`() { // -, 1000 assertTimeout(ofMillis(1000)) { print(" , 1 ") Thread.sleep(3) } }
assertTimeoutPreemptively
method: @Test fun `Timeout not exceeded with preemptively exit`() { // , 1000 assertTimeoutPreemptively(ofMillis(1000)) { print(" , 1 ") Thread.sleep(3) } }
import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.containsInAnyOrder import org.hamcrest.Matchers.greaterThanOrEqualTo import org.hamcrest.Matchers.hasItem import org.hamcrest.Matchers.notNullValue import org.junit.jupiter.api.Test class HamcrestExample { @Test fun `Some examples`() { val list = listOf("s1", "s2", "s3") assertThat(list, containsInAnyOrder("s3", "s1", "s2")) assertThat(list, hasItem("s1")) assertThat(list.size, greaterThanOrEqualTo(3)) assertThat(list[0], notNullValue()) } }
import org.junit.jupiter.api.Assumptions.assumeTrue import org.junit.jupiter.api.Test class AssumptionTest { @Test fun `Test Java 8 installed`() { assumeTrue(System.getProperty("java.version").startsWith("1.8")) print("Not too old version") } @Test fun `Test Java 7 installed`() { assumeTrue(System.getProperty("java.version").startsWith("1.7")) { "Assumption doesn't hold" } print("Need to update") } }
Person
class a data class, which, among other things, will override the toString()
method, and add the birthDate
and age
properties: import java.time.LocalDate import java.time.Period data class Person(val firstName: String, val lastName: String, val birthDate: LocalDate?) { val age get() = Period.between(this.birthDate, LocalDate.now()).years }
import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.DynamicTest import org.junit.jupiter.api.DynamicTest.dynamicTest import org.junit.jupiter.api.TestFactory import java.time.LocalDate class TestFactoryExample { @TestFactory fun `Run multiple tests`(): Collection<DynamicTest> { val persons = listOf( Person("John", "Doe", LocalDate.of(1969, 5, 20)), Person("Jane", "Smith", LocalDate.of(1997, 11, 21)), Person("Ivan", "Ivanov", LocalDate.of(1994, 2, 12)) ) val minAgeFilter = 18 return persons.map { dynamicTest("Check person $it on age greater or equals $minAgeFilter") { assertTrue(it.age >= minAgeFilter) } }.toList() } }
DynamicTest
collections, in the method annotated by @TestFactory
, you can return Stream
, Iterable
, Iterator
.@Test
methods in that the method annotated by the @BeforeEach
only performed for the @TestFactory
method, and not for each dynamic test. For example, when executing the following code, the Reset some var
function will be called only once, as can be seen using the variable someVar
: private var someVar: Int? = null @BeforeEach fun `Reset some var`() { someVar = 0 } @TestFactory fun `Test factory`(): Collection<DynamicTest> { val ints = 0..5 return ints.map { dynamicTest("Test №$it incrementing some var") { someVar = someVar?.inc() print(someVar) } }.toList() }
@TestFactory
. To illustrate the operation of this method, we first add the dependency to pom.xml
: <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.0.2</version> <scope>test</scope> </dependency>
class ParameterizedTestExample { @ParameterizedTest @ValueSource(strings = ["2002-01-23", "1956-03-14", "1503-07-19"]) fun `Check date in past`(date: LocalDate) { assertTrue(date.isBefore(LocalDate.now())) } }
@ValueSource
annotation @ValueSource
can be arrays int
, long
, double
and String
. In the case of an array of strings, as can be seen from the example above, an implicit conversion to the type of the input parameter will be used if it is possible. @ValueSource
allows @ValueSource
to pass only one input parameter for each test call.@EnumSource
allows the test method to accept enum constants: @ParameterizedTest @EnumSource(TimeUnit::class) fun `Test enum`(timeUnit: TimeUnit) { assertNotNull(timeUnit) }
@ParameterizedTest @EnumSource(TimeUnit::class, mode = EnumSource.Mode.EXCLUDE, names = ["SECONDS", "MINUTES"]) fun `Test enum without days and milliseconds`(timeUnit: TimeUnit) { print(timeUnit) }
@ParameterizedTest @MethodSource("intProvider") fun `Test with custom arguments provider`(argument: Int) { assertNotNull(argument) } companion object { @JvmStatic fun intProvider(): Stream<Int> = Stream.of(0, 42, 9000) }
@JvmStatic
. To use a non-static method, you need to change the life cycle of the test instance, more precisely, create one instance of the test per class, instead of one instance per method, as is done by default: @TestInstance(TestInstance.Lifecycle.PER_CLASS) class ParameterizedTestExample { @ParameterizedTest @MethodSource("intProvider") fun `Test with custom arguments provider`(argument: Int) { assertNotNull(argument) } fun intProvider(): Stream<Int> = Stream.of(0, 42, 9000) }
@RepeatedTest(10) fun ` `() { }
@RepeatedTest(10, name = "{displayName} {currentRepetition} {totalRepetitions}") fun ` `() { }
@RepeatedTest(5) fun `Repeated test with repetition info and test info`(repetitionInfo: RepetitionInfo, testInfo: TestInfo) { assertEquals(5, repetitionInfo.totalRepetitions) val testDisplayNameRegex = """repetition \d of 5""".toRegex() assertTrue(testInfo.displayName.matches(testDisplayNameRegex)) }
Person
class and our own provider of test arguments that returns a stream of Person
objects: class NestedTestExample { @Nested inner class `Check age of person` { @ParameterizedTest @ArgumentsSource(PersonProvider::class) fun `Check age greater or equals 18`(person: Person) { assertTrue(person.age >= 18) } @ParameterizedTest @ArgumentsSource(PersonProvider::class) fun `Check birth date is after 1950`(person: Person) { assertTrue(LocalDate.of(1950, 12, 31).isBefore(person.birthDate)) } } @Nested inner class `Check name of person` { @ParameterizedTest @ArgumentsSource(PersonProvider::class) fun `Check first name length is 4`(person: Person) { assertEquals(4, person.firstName.length) } } internal class PersonProvider : ArgumentsProvider { override fun provideArguments(context: ExtensionContext): Stream<out Arguments> = Stream.of( Person("John", "Doe", LocalDate.of(1969, 5, 20)), Person("Jane", "Smith", LocalDate.of(1997, 11, 21)), Person("Ivan", "Ivanov", LocalDate.of(1994, 2, 12)) ).map { Arguments.of(it) } } }
Source: https://habr.com/ru/post/346452/
All Articles