mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
Introduce 'fail' method to throw AssertionError with cause
#KT-37804
This commit is contained in:
@@ -92,6 +92,17 @@ fun fail(message: String? = null): Nothing {
|
||||
asserter.fail(message)
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a test as having failed if this point in the execution path is reached, with an optional [message]
|
||||
* and [cause] exception.
|
||||
*
|
||||
* The [cause] exception is set as the root cause of the test failure.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
fun fail(message: String? = null, cause: Throwable? = null): Nothing {
|
||||
asserter.fail(message, cause)
|
||||
}
|
||||
|
||||
/** Asserts that given function [block] returns the given [expected] value. */
|
||||
fun <@OnlyInputTypes T> expect(expected: T, block: () -> T) {
|
||||
assertEquals(expected, block())
|
||||
@@ -173,6 +184,8 @@ inline fun <T : Throwable> assertFailsWith(exceptionClass: KClass<T>, block: ()
|
||||
inline fun <T : Throwable> assertFailsWith(exceptionClass: KClass<T>, message: String?, block: () -> Unit): T =
|
||||
checkResultIsFailure(exceptionClass, message, runCatching(block))
|
||||
|
||||
/** Platform-specific construction of AssertionError with cause */
|
||||
internal expect fun AssertionErrorWithCause(message: String?, cause: Throwable?): AssertionError
|
||||
|
||||
/**
|
||||
* Abstracts the logic for performing assertions. Specific implementations of [Asserter] can use JUnit
|
||||
@@ -186,6 +199,15 @@ interface Asserter {
|
||||
*/
|
||||
fun fail(message: String?): Nothing
|
||||
|
||||
/**
|
||||
* Fails the current test with the specified message and cause exception.
|
||||
*
|
||||
* @param message the message to report.
|
||||
* @param cause the exception to set as the root cause of the reported failure.
|
||||
*/
|
||||
@SinceKotlin("1.4")
|
||||
fun fail(message: String?, cause: Throwable?): Nothing
|
||||
|
||||
/**
|
||||
* Asserts that the specified value is `true`.
|
||||
*
|
||||
|
||||
@@ -15,6 +15,11 @@ object DefaultAsserter : Asserter {
|
||||
else
|
||||
throw AssertionError(message)
|
||||
}
|
||||
|
||||
@SinceKotlin("1.4")
|
||||
override fun fail(message: String?, cause: Throwable?): Nothing {
|
||||
throw AssertionErrorWithCause(message, cause)
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("DefaultAsserter is an object now, constructor call is not required anymore",
|
||||
|
||||
@@ -148,7 +148,7 @@ class BasicAssertionsTest {
|
||||
|
||||
@Test()
|
||||
fun testAssertNotNullFails() {
|
||||
checkFailedAssertion { assertNotNull(null) }
|
||||
checkFailedAssertion { assertNotNull<Any>(null) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -178,7 +178,18 @@ class BasicAssertionsTest {
|
||||
|
||||
@Test()
|
||||
fun testFail() {
|
||||
checkFailedAssertion { fail("should fail") }
|
||||
val message = "should fail"
|
||||
val actual = checkFailedAssertion { fail(message) }
|
||||
assertEquals(message, actual.message)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFailWithCause() {
|
||||
val message = "should fail due to"
|
||||
val cause = IllegalStateException()
|
||||
val actual = checkFailedAssertion { fail(message, cause) }
|
||||
assertEquals(message, actual.message)
|
||||
assertSame(cause, actual.cause)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -193,8 +204,8 @@ class BasicAssertionsTest {
|
||||
}
|
||||
|
||||
|
||||
private fun checkFailedAssertion(assertion: () -> Unit) {
|
||||
assertFailsWith<AssertionError> { withDefaultAsserter(assertion) }
|
||||
private fun checkFailedAssertion(assertion: () -> Unit): AssertionError {
|
||||
return assertFailsWith<AssertionError> { withDefaultAsserter(assertion) }
|
||||
}
|
||||
|
||||
private fun withDefaultAsserter(block: () -> Unit) {
|
||||
|
||||
@@ -57,7 +57,7 @@ internal object DefaultJsAsserter : Asserter {
|
||||
|
||||
override fun assertTrue(lazyMessage: () -> String?, actual: Boolean) {
|
||||
if (!actual) {
|
||||
failWithMessage(lazyMessage)
|
||||
failWithMessage(lazyMessage, null)
|
||||
} else {
|
||||
invokeHook(true, lazyMessage)
|
||||
}
|
||||
@@ -68,16 +68,18 @@ internal object DefaultJsAsserter : Asserter {
|
||||
}
|
||||
|
||||
override fun fail(message: String?): Nothing {
|
||||
failWithMessage { message }
|
||||
fail(message, null)
|
||||
}
|
||||
|
||||
private fun failWithMessage(lazyMessage: () -> String?): Nothing {
|
||||
@SinceKotlin("1.4")
|
||||
override fun fail(message: String?, cause: Throwable?): Nothing {
|
||||
failWithMessage({ message }, cause)
|
||||
}
|
||||
|
||||
private inline fun failWithMessage(lazyMessage: () -> String?, cause: Throwable?): Nothing {
|
||||
val message = lazyMessage()
|
||||
invokeHook(false) { message }
|
||||
if (message == null)
|
||||
throw AssertionError()
|
||||
else
|
||||
throw AssertionError(message)
|
||||
throw AssertionErrorWithCause(message, cause)
|
||||
}
|
||||
|
||||
private fun invokeHook(result: Boolean, lazyMessage: () -> String?) {
|
||||
|
||||
@@ -17,6 +17,11 @@ actual fun todo(block: () -> Unit) {
|
||||
println("TODO at " + block)
|
||||
}
|
||||
|
||||
/** Platform-specific construction of AssertionError with cause */
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal actual inline fun AssertionErrorWithCause(message: String?, cause: Throwable?): AssertionError =
|
||||
AssertionError(message, cause)
|
||||
|
||||
|
||||
@PublishedApi
|
||||
internal actual fun <T : Throwable> checkResultIsFailure(exceptionClass: KClass<T>, message: String?, blockResult: Result<Unit>): T {
|
||||
|
||||
@@ -57,4 +57,16 @@ object JUnitAsserter : Asserter {
|
||||
// should not get here
|
||||
throw AssertionError(message)
|
||||
}
|
||||
|
||||
@SinceKotlin("1.4")
|
||||
override fun fail(message: String?, cause: Throwable?): Nothing {
|
||||
try {
|
||||
Assert.fail(message)
|
||||
} catch (e: AssertionError) {
|
||||
e.initCause(cause)
|
||||
throw e
|
||||
}
|
||||
// should not get here
|
||||
throw AssertionError(message).initCause(cause)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,15 @@ object JUnit5Asserter : Asserter {
|
||||
}
|
||||
|
||||
override fun fail(message: String?): Nothing {
|
||||
Assertions.fail<Any>(message)
|
||||
Assertions.fail<Any?>(message)
|
||||
// should not get here
|
||||
throw AssertionError(message)
|
||||
}
|
||||
|
||||
@SinceKotlin("1.4")
|
||||
override fun fail(message: String?, cause: Throwable?): Nothing {
|
||||
Assertions.fail<Any?>(message, cause)
|
||||
// should not get here
|
||||
throw AssertionError(message, cause)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,3 +72,10 @@ actual inline fun todo(@Suppress("UNUSED_PARAMETER") block: () -> Unit) {
|
||||
@InlineOnly
|
||||
inline fun currentStackTrace() = @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") (java.lang.Exception() as java.lang.Throwable).stackTrace
|
||||
|
||||
|
||||
/** Platform-specific construction of AssertionError with cause */
|
||||
internal actual fun AssertionErrorWithCause(message: String?, cause: Throwable?): AssertionError {
|
||||
val assertionError = if (message == null) AssertionError() else AssertionError(message)
|
||||
assertionError.initCause(cause)
|
||||
return assertionError
|
||||
}
|
||||
|
||||
@@ -57,4 +57,11 @@ object TestNGAsserter : Asserter {
|
||||
// should not get here
|
||||
throw AssertionError(message)
|
||||
}
|
||||
|
||||
@SinceKotlin("1.4")
|
||||
override fun fail(message: String?, cause: Throwable?): Nothing {
|
||||
Assert.fail(message, cause)
|
||||
// should not get here
|
||||
throw AssertionError(message).initCause(cause)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,8 @@ public actual open class AssertionError : Error {
|
||||
public actual constructor() : super()
|
||||
public constructor(message: String?) : super(message)
|
||||
public actual constructor(message: Any?) : super(message?.toString(), message as? Throwable)
|
||||
@SinceKotlin("1.4")
|
||||
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||
}
|
||||
|
||||
public actual open class NoSuchElementException : RuntimeException {
|
||||
|
||||
@@ -80,7 +80,9 @@ public actual open class ClassCastException actual constructor(message: String?)
|
||||
actual constructor() : this(null)
|
||||
}
|
||||
|
||||
public actual open class AssertionError private constructor(message: String?, cause: Throwable?) : Error(message, cause) {
|
||||
public actual open class AssertionError
|
||||
@SinceKotlin("1.4")
|
||||
constructor(message: String?, cause: Throwable?) : Error(message, cause) {
|
||||
actual constructor() : this(null)
|
||||
constructor(message: String?) : this(message, null)
|
||||
actual constructor(message: Any?) : this(message.toString(), message as? Throwable)
|
||||
|
||||
Reference in New Issue
Block a user