Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ repository on GitHub.
option to change it. To resolve this, a new `commentCharacter` attribute has been added
to both annotations. Its default value remains `+++#+++`, but it can now be customized
to avoid conflicts with other control characters.
* Fix `IllegalAccessError` thrown when using the Kotlin-specific `assertDoesNotThrow`
assertion.

[[release-notes-6.0.1-junit-jupiter-deprecations-and-breaking-changes]]
==== Deprecations and Breaking Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ package org.junit.jupiter.api
import org.apiguardian.api.API
import org.apiguardian.api.API.Status.MAINTAINED
import org.apiguardian.api.API.Status.STABLE
import org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure
import org.junit.jupiter.api.function.Executable
import org.junit.platform.commons.util.UnrecoverableExceptions.rethrowIfUnrecoverable
import java.time.Duration
Expand Down Expand Up @@ -347,7 +348,6 @@ inline fun <reified T : Throwable> assertThrows(
* @see Assertions.assertDoesNotThrow
* @param R the result type of the [executable]
*/
@Suppress("LESS_VISIBLE_TYPE_ACCESS_IN_INLINE_WARNING")
@OptIn(ExperimentalContracts::class)
@API(status = STABLE, since = "5.11")
inline fun <R> assertDoesNotThrow(executable: () -> R): R {
Expand All @@ -359,7 +359,11 @@ inline fun <R> assertDoesNotThrow(executable: () -> R): R {
return executable()
} catch (t: Throwable) {
rethrowIfUnrecoverable(t)
throw AssertDoesNotThrow.createAssertionFailedError(null, t)
val suffix = t.message?.let { if (it.isNotBlank()) ": ${t.message}" else null } ?: ""
throw assertionFailure()
.reason("Unexpected exception thrown: ${t.javaClass.getName()}$suffix")
.cause(t)
.build()
}
}

Expand Down Expand Up @@ -396,7 +400,6 @@ inline fun <R> assertDoesNotThrow(
* @see Assertions.assertDoesNotThrow
* @param R the result type of the [executable]
*/
@Suppress("LESS_VISIBLE_TYPE_ACCESS_IN_INLINE_WARNING")
@OptIn(ExperimentalContracts::class)
@API(status = STABLE, since = "5.11")
inline fun <R> assertDoesNotThrow(
Expand All @@ -412,7 +415,12 @@ inline fun <R> assertDoesNotThrow(
return executable()
} catch (t: Throwable) {
rethrowIfUnrecoverable(t)
throw AssertDoesNotThrow.createAssertionFailedError(message(), t)
val suffix = t.message?.let { if (it.isNotBlank()) ": ${t.message}" else null } ?: ""
throw assertionFailure()
.message(message())
.reason("Unexpected exception thrown: ${t.javaClass.getName()}$suffix")
.cause(t)
.build()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,48 @@

package org.junit.jupiter.api;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

import org.apache.groovy.parser.antlr4.util.StringUtils;
import org.jspecify.annotations.Nullable;
import org.opentest4j.AssertionFailedError;
import org.opentest4j.MultipleFailuresError;
import org.opentest4j.ValueWrapper;

class AssertionTestUtils {
public class AssertionTestUtils {

private AssertionTestUtils() {
/* no-op */
}

static void expectAssertionFailedError() {
public static void expectAssertionFailedError() {
throw new AssertionError("Should have thrown an " + AssertionFailedError.class.getName());
}

static void assertEmptyMessage(Throwable ex) throws AssertionError {
if (!StringUtils.isEmpty(ex.getMessage())) {
public static void assertEmptyMessage(Throwable ex) throws AssertionError {
if (!(ex.getMessage() == null || ex.getMessage().isEmpty())) {
throw new AssertionError("Exception message should be empty, but was [" + ex.getMessage() + "].");
}
}

static void assertMessageEquals(Throwable ex, String msg) throws AssertionError {
public static void assertMessageEquals(Throwable ex, String msg) throws AssertionError {
if (!msg.equals(ex.getMessage())) {
throw new AssertionError("Exception message should be [" + msg + "], but was [" + ex.getMessage() + "].");
}
}

static void assertMessageMatches(Throwable ex, String regex) throws AssertionError {
public static void assertMessageMatches(Throwable ex, String regex) throws AssertionError {
if (ex.getMessage() == null || !ex.getMessage().matches(regex)) {
throw new AssertionError("Exception message should match regular expression [" + regex + "], but was ["
+ ex.getMessage() + "].");
}
}

static void assertMessageStartsWith(@Nullable Throwable ex, String msg) throws AssertionError {
public static void assertMessageStartsWith(@Nullable Throwable ex, String msg) throws AssertionError {
if (ex == null) {
throw new AssertionError("Cause should not have been null");
}
Expand All @@ -57,14 +61,14 @@ static void assertMessageStartsWith(@Nullable Throwable ex, String msg) throws A
}
}

static void assertMessageEndsWith(Throwable ex, String msg) throws AssertionError {
public static void assertMessageEndsWith(Throwable ex, String msg) throws AssertionError {
if (ex.getMessage() == null || !ex.getMessage().endsWith(msg)) {
throw new AssertionError(
"Exception message should end with [" + msg + "], but was [" + ex.getMessage() + "].");
}
}

static void assertMessageContains(@Nullable Throwable ex, String msg) throws AssertionError {
public static void assertMessageContains(@Nullable Throwable ex, String msg) throws AssertionError {
if (ex == null) {
throw new AssertionError("Cause should not have been null");
}
Expand All @@ -74,7 +78,7 @@ static void assertMessageContains(@Nullable Throwable ex, String msg) throws Ass
}
}

static void assertExpectedAndActualValues(AssertionFailedError ex, @Nullable Object expected,
public static void assertExpectedAndActualValues(AssertionFailedError ex, @Nullable Object expected,
@Nullable Object actual) throws AssertionError {
if (!wrapsEqualValue(ex.getExpected(), expected)) {
throw new AssertionError("Expected value in AssertionFailedError should equal ["
Expand All @@ -86,7 +90,7 @@ static void assertExpectedAndActualValues(AssertionFailedError ex, @Nullable Obj
}
}

static boolean wrapsEqualValue(ValueWrapper wrapper, @Nullable Object value) {
public static boolean wrapsEqualValue(ValueWrapper wrapper, @Nullable Object value) {
if (value == null || value instanceof Serializable) {
return Objects.equals(value, wrapper.getValue());
}
Expand All @@ -95,14 +99,32 @@ static boolean wrapsEqualValue(ValueWrapper wrapper, @Nullable Object value) {
&& Objects.equals(wrapper.getType(), value.getClass());
}

static void recurseIndefinitely() {
public static void recurseIndefinitely() {
// simulate infinite recursion
throw new StackOverflowError();
}

static void runOutOfMemory() {
public static void runOutOfMemory() {
// simulate running out of memory
throw new OutOfMemoryError("boom");
}

@SafeVarargs
public static void assertExpectedExceptionTypes(MultipleFailuresError multipleFailuresError,
Class<? extends Throwable>... exceptionTypes) {

assertNotNull(multipleFailuresError, "MultipleFailuresError");
List<Throwable> failures = multipleFailuresError.getFailures();
assertEquals(exceptionTypes.length, failures.size(), "number of failures");

// Verify that exceptions are also present as suppressed exceptions.
// https://github.com/junit-team/junit-framework/issues/1602
Throwable[] suppressed = multipleFailuresError.getSuppressed();
assertEquals(exceptionTypes.length, suppressed.length, "number of suppressed exceptions");

for (int i = 0; i < exceptionTypes.length; i++) {
assertEquals(exceptionTypes[i], failures.get(i).getClass(), "exception type [" + i + "]");
assertEquals(exceptionTypes[i], suppressed[i].getClass(), "suppressed exception type [" + i + "]");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.AssertionTestUtils.assertExpectedExceptionTypes;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.platform.commons.test.PreconditionAssertions.assertPreconditionViolationNotNullFor;
import static org.junit.platform.commons.test.PreconditionAssertions.assertPreconditionViolationNotNullOrEmptyFor;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

import org.junit.jupiter.api.function.Executable;
Expand Down Expand Up @@ -198,25 +197,6 @@ void assertAllWithParallelStream() {
assertThat(multipleFailuresError.getFailures()).hasSize(100).doesNotContainNull();
}

@SafeVarargs
static void assertExpectedExceptionTypes(MultipleFailuresError multipleFailuresError,
Class<? extends Throwable>... exceptionTypes) {

assertNotNull(multipleFailuresError, "MultipleFailuresError");
List<Throwable> failures = multipleFailuresError.getFailures();
assertEquals(exceptionTypes.length, failures.size(), "number of failures");

// Verify that exceptions are also present as suppressed exceptions.
// https://github.com/junit-team/junit-framework/issues/1602
Throwable[] suppressed = multipleFailuresError.getSuppressed();
assertEquals(exceptionTypes.length, suppressed.length, "number of suppressed exceptions");

for (int i = 0; i < exceptionTypes.length; i++) {
assertEquals(exceptionTypes[i], failures.get(i).getClass(), "exception type [" + i + "]");
assertEquals(exceptionTypes[i], suppressed[i].getClass(), "suppressed exception type [" + i + "]");
}
}

@SuppressWarnings("serial")
private static class EnigmaThrowable extends Throwable {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,26 @@
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api
package org.junit.jupiter.api.kotlin

import org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals
import org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.assertTimeout
import org.junit.jupiter.api.assertTimeoutPreemptively
import org.junit.jupiter.api.fail
import org.junit.platform.commons.util.ExceptionUtils
import org.opentest4j.AssertionFailedError
import java.time.Duration.ofMillis
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicBoolean

/**
* Unit tests for JUnit Jupiter [Assertions].
* Unit tests for Kotlin-specific `assertTimeout*` assertions.
*
* @since 5.5
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,27 @@
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api
package org.junit.jupiter.api.kotlin

import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.AssertionTestUtils
import org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals
import org.junit.jupiter.api.AssertionTestUtils.assertMessageStartsWith
import org.junit.jupiter.api.AssertionTestUtils.expectAssertionFailedError
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DynamicContainer.dynamicContainer
import org.junit.jupiter.api.DynamicNode
import org.junit.jupiter.api.DynamicTest.dynamicTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestFactory
import org.junit.jupiter.api.assertAll
import org.junit.jupiter.api.assertDoesNotThrow
import org.junit.jupiter.api.assertInstanceOf
import org.junit.jupiter.api.assertNull
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.fail
import org.opentest4j.AssertionFailedError
import org.opentest4j.MultipleFailuresError
import java.util.stream.Stream
Expand Down Expand Up @@ -70,7 +80,7 @@ class KotlinAssertionsTests {
}

@TestFactory
fun assertDoesNotThrow(): Stream<out DynamicNode> =
fun `assertDoesNotThrow behaves as expected`(): Stream<out DynamicNode> =
Stream.of(
dynamicContainer(
"succeeds when no exception thrown",
Expand Down Expand Up @@ -223,7 +233,7 @@ class KotlinAssertionsTests {
}

@Test
fun assertInstanceOf() {
fun `assertInstanceOf succeeds`() {
assertInstanceOf<RandomAccess>(listOf("whatever"))
assertInstanceOf<RandomAccess>(listOf("whatever"), "No random access")
assertInstanceOf<RandomAccess>(listOf("whatever")) { "No random access" }
Expand Down Expand Up @@ -336,7 +346,7 @@ class KotlinAssertionsTests {
fun assertExpectedExceptionTypes(
multipleFailuresError: MultipleFailuresError,
vararg exceptionTypes: KClass<out Throwable>
) = AssertAllAssertionsTests.assertExpectedExceptionTypes(
) = AssertionTestUtils.assertExpectedExceptionTypes(
multipleFailuresError,
*exceptionTypes.map { it.java }.toTypedArray()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,21 @@
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api
package org.junit.jupiter.api.kotlin

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.DynamicTest.dynamicTest
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.TestFactory
import java.math.BigDecimal
import java.math.BigDecimal.ONE
import java.math.MathContext
import java.math.BigInteger as BigInt
import java.math.RoundingMode as Rounding

/**
* Unit tests for JUnit Jupiter [TestFactory] use in kotlin classes.
* Unit tests for JUnit Jupiter [org.junit.jupiter.api.TestFactory] use in kotlin classes.
*
* @since 5.12
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api
package org.junit.jupiter.api.kotlin

import org.junit.jupiter.api.AssertEquals.assertEquals
import org.junit.jupiter.api.AssertionTestUtils.assertEmptyMessage
import org.junit.jupiter.api.AssertionTestUtils.assertMessageContains
import org.junit.jupiter.api.AssertionTestUtils.assertMessageEquals
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import org.junit.jupiter.api.fail
import org.opentest4j.AssertionFailedError
import java.util.stream.Stream

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.api
package org.junit.jupiter.api.kotlin

import kotlinx.coroutines.runBlocking
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.DynamicTest.dynamicTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestFactory
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
import org.junit.jupiter.api.TestReporter
import org.junit.jupiter.engine.AbstractJupiterTestEngineTests
import org.junit.jupiter.params.AfterParameterizedClassInvocation
import org.junit.jupiter.params.BeforeParameterizedClassInvocation
Expand Down