Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Kotlin friendly assertInstanceOf assertions #3492

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -51,7 +51,6 @@ JUnit repository on GitHub.
* Documentation for `@Disabled` and conditional annotations now explicitly explains that
such annotations are not inherited by subclasses.


[[release-notes-5.10.1-junit-vintage]]
=== JUnit Vintage

Expand Down
Expand Up @@ -111,6 +111,8 @@ page in the Wiki.
the supplied message is not the _expected message_ of the thrown exception.
* Improved documentation for semantics of a disabled test regarding class-level lifecycle
methods and callbacks.
* New `assertInstanceOf` methods added for Kotlin following up with similar Java
`assertInstanceOf` methods introduced in `5.8` version.


[[release-notes-5.11.0-M1-junit-vintage]]
Expand Down
Expand Up @@ -14,6 +14,9 @@ tasks.withType<KotlinCompile>().configureEach {
apiVersion = "1.6"
languageVersion = "1.6"
allWarningsAsErrors = false
// Compiler arg is required for Kotlin 1.6 and below
// see https://kotlinlang.org/docs/whatsnew17.html#stable-opt-in-requirements
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
}
}

Expand Down
Expand Up @@ -19,6 +19,8 @@ import org.junit.jupiter.api.function.ThrowingSupplier
import java.time.Duration
import java.util.function.Supplier
import java.util.stream.Stream
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract

/**
* @see Assertions.fail
Expand Down Expand Up @@ -287,3 +289,33 @@ fun <R> assertTimeoutPreemptively(timeout: Duration, message: String, executable
@API(status = EXPERIMENTAL, since = "5.5")
fun <R> assertTimeoutPreemptively(timeout: Duration, message: () -> String, executable: () -> R): R =
Assertions.assertTimeoutPreemptively(timeout, executable, message)

/**
* Example usage:
* ```kotlin
* assertInstanceOf<RandomAccess>(list, "List should support fast random access")
* ```
* @see Assertions.assertInstanceOf
* @since 5.11
*/
@OptIn(ExperimentalContracts::class)
@API(status = EXPERIMENTAL, since = "5.11")
inline fun <reified T : Any> assertInstanceOf(actualValue: Any?, message: String? = null): T {
contract {
returns() implies (actualValue is T)
}
return Assertions.assertInstanceOf(T::class.java, actualValue, message)
}

/*
* @see Assertions.assertInstanceOf
* @since 5.11
*/
@OptIn(ExperimentalContracts::class)
@API(status = EXPERIMENTAL, since = "5.11")
inline fun <reified T : Any> assertInstanceOf(actualValue: Any?, noinline message: () -> String): T {
contract {
returns() implies (actualValue is T)
}
return Assertions.assertInstanceOf(T::class.java, actualValue, message)
}
Expand Up @@ -211,6 +211,29 @@ class KotlinAssertionsTests {
assertMessageStartsWith(error, assertionMessage)
}

@Test
fun assertInstanceOf() {
assertInstanceOf<RandomAccess>(listOf("whatever"))
assertInstanceOf<RandomAccess>(listOf("whatever"), "No random access")
assertInstanceOf<RandomAccess>(listOf("whatever")) { "No random access" }
}

@Test
fun `assertInstanceOf fails wrong type value`() {
val result = assertThrows<AssertionError> {
assertInstanceOf<String>(StringBuilder(), "Should be a String")
}
assertMessageStartsWith(result, "Should be a String")
}

@Test
fun `assertInstanceOf fails null value`() {
val result = assertThrows<AssertionError> {
assertInstanceOf<String>(null, "Should be a String")
}
assertMessageStartsWith(result, "Should be a String")
}

companion object {
fun assertExpectedExceptionTypes(
multipleFailuresError: MultipleFailuresError,
Expand Down