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

Inline lambdas passed to assertDoesNotThrows to support suspending functions #2684

Conversation

williamboman
Copy link
Contributor

@williamboman williamboman commented Aug 11, 2021

Resolves #2674.

Overview

Support for suspending functions was added for the assertThrows() counterpart (see #1851), but it seems like calling suspending functions in an assertDoesNotThrow() block is currently not supported.


I hereby agree to the terms of the JUnit Contributor License Agreement.


Definition of Done

@@ -147,6 +147,14 @@ inline fun <reified T : Throwable> assertThrows(noinline message: () -> String,
}, Supplier(message))
}

@PublishedApi
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, possibly dumb question here, but why do we need this method to be inline?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, could you please move this method below the other ones calling it? :)

Copy link
Contributor Author

@williamboman williamboman Aug 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, possibly dumb question here, but why do we need this method to be inline?

Because this function is ultimately the one responsible for calling the provided executable. We want to run the executable in the same context as the callsite of assertDoesNotThrow (so that it can suspend, etc.), so we need to make sure the full call stack from assertDoesNotThrow until here uses inlined functions. If we were to remove the inline modifier on this function, we'll get a compiler error in all of the assertDoesNotThrow functions saying that we're violating the inlineability (I totally just made that word up) of the executable argument, and that we need to change the function signature to assertDoesNotThrow(noinline executable: () -> R). Doing so breaks the tests that now calls a suspending function, because the callback is no longer inlined.

edit: This is at least my understanding

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see! Thanks for the explanation 😄

…ow-coroutines

* upstream/main:
  Introduce AnnotationSupport.findAnnotation() that searches enclosing classes
  Introduce unit tests for AnnotationUtils.findAnnotation(Class,Class,boolean)
  Always include classes selected via @SelectClasses in suites
  Polishing
  Polishing
  Fix TypedArgumentConverter example in User Guide
  Ensure TypedArgumentConverter can convert to a primitive
  Introduce ReflectionUtils.isAssignableTo(Class,Class)
  Fix Javadoc tag in TypedArgumentConverter
@Test
fun `assertDoesNotThrow with coroutines`() = runBlocking {
val result = assertDoesNotThrow {
suspend { "Result" }()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to have another test with a suspending function that actually throws an exception (thus making the test fail), since we want to make sure that the assertion is actually waiting for the "throwing"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed the test factory below, you could even add one dynamic test in each dynamicContainer for this new suspending function use case :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! d48eeb4

@juliette-derancourt juliette-derancourt marked this pull request as ready for review August 13, 2021 17:14
@codecov
Copy link

codecov bot commented Aug 13, 2021

Codecov Report

Merging #2684 (742d7af) into main (718d730) will decrease coverage by 0.10%.
The diff coverage is 0.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #2684      +/-   ##
==========================================
- Coverage   91.47%   91.37%   -0.11%     
==========================================
  Files         427      427              
  Lines       12067    12075       +8     
  Branches      941      941              
==========================================
- Hits        11038    11033       -5     
- Misses        788      801      +13     
  Partials      241      241              
Impacted Files Coverage Δ
...rc/main/kotlin/org/junit/jupiter/api/Assertions.kt 40.00% <0.00%> (-22.97%) ⬇️
.../junit/platform/commons/logging/LoggerFactory.java 71.87% <0.00%> (-3.13%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 718d730...742d7af. Read the comment docs.

@juliette-derancourt
Copy link
Member

@williamboman could you please add an entry in the release notes?

…ow-coroutines

* upstream/main:
  Upgradle to 7.2-rc-3
  Improve documentation on tags in User Guide
  Polishing
  Discover suite tests using parent configuration parameters
  Add support for private TempDir fields
  Document junit-team#2582 in release notes
  Simplify test
  Report exceptions thrown by CloseableResource as suppressed exceptions
  Use temp dir in constructor resolution test case
  Document scope in Javadoc
  Document configuration parameter
  Rename TempDirBehavior to TempDirectory.Scope
  Document in user guide
  Add to release notes
  Change TempDir to create a separate dir per declaration
  Split test case
  Reduce scope of SuppressWarnings annotation
  Revert "Add identifier element to `TempDir` annotation"
@williamboman
Copy link
Contributor Author

@williamboman could you please add an entry in the release notes?

Done! Struggled a bit with the wording (for example, not sure if need to clarify it's Kotlin API or if that's implied), feel free to amend!

)

@PublishedApi
internal inline fun <R> getThrowingSupplier(executable: () -> R): ThrowingSupplier<R> = try {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this method name which is "effectively public" due to @PublishedApi. Maybe evaluateAndWrap or sth. similar would be clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's a good call, agreed.

742d7af

@juliette-derancourt juliette-derancourt merged commit 3f605f1 into junit-team:main Aug 17, 2021
@juliette-derancourt juliette-derancourt added this to the 5.8 RC1 milestone Aug 17, 2021
@sbrannen sbrannen removed this from the 5.8 RC1 milestone Aug 17, 2021
@williamboman williamboman deleted the assert-does-not-throw-coroutines branch August 17, 2021 14:57
runningcode pushed a commit to runningcode/junit5 that referenced this pull request Feb 15, 2023
…nctions (junit-team#2684)

This commit adds support for suspending functions when `assertDoesNotThrow` is called from Kotlin.

Closes junit-team#2674.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support assertDoesNotThrow() with suspending functions in Kotlin
4 participants