Open changusmc opened 5 years ago
Just piping up to point out that this is slightly different than previous discussions about assertThrows()
insofar as (a) 4.13 isn't released, despite it having betas and being internally used in Google, so not everyone will have assertThrows from JUnit handy in their deps, (b) I've now seen several cases of people including a dep on kotlin.test exclusively for assertFailsWith<SomeErrorType> { lambda logic }
while using Truth for everything else.
While I think it kind of made sense before when we were certain everyone would have this (or equivalent) function in their deps, I don't think that's a sound assumption under present conditions.
(Trying to head off objections that I've already heard inside Google to related inquiries, since I think we're in a different situation than that in which those discussions occurred)
/cc @cushon @cpovirk @lowasser
related: b/114409026
The linked API is notably different (and more usable, not that I'm biased as its author) than JUnit and kotlin.test.
In Kotlin, for JUnit, you have to use assertThrows(IllegalStateException::class.java) { .. }
whereas this function requires only assertThrows<IllegalStateException> { .. }
. Having to specify ::class.java
isn't going to kill anyone, but it's visual clutter. kotlin.test gets to share the same nice syntax.
Beyond that, the other APIs immediately fall short. JUnit lets you assert on the exact message but nothing like start/end/regex-based matching. For that, you need to change how you assert by capturing the return value and asserting on the message or wrapping in a ThrowableSubject
and then asserting.
Similarly, any causal analysis requires capturing the Throwable
, wrapping, and then analyzing.
The above snippet returns the ThrowableSubject
directly which lets you immediately chain into any of these more advanced assertions, or combine them in an apply
block.
assertThrows<IllegalStateException> {
...
}.apply {
hasMessage().startsWith("Whatever: ")
hasCause().isInstanceOf(SomeException::class.java)
}
I really do like @JakeWharton's variant, but I'm not sure if this can be achieved from within Java, so there are a few things questions this forces.
Personally I'd love to see Jake's flavor, but we also have a lot of Java left.
Is this issue here about Kotlin only? From the title of this issue it sounds to be generic, but the comments here seem to be mostly / only about Kotlin.
Even for Java projects a Truth assertThrows
method would be useful:
ThrowableSubject
to allow directly performing assertions on the exceptionMaybe it would also be useful to have two flavors: One assertThrows
which checks if the exception class is equal, and another one which checks if the class is an instanceof
.
Yes, I'm not keen to add a JUnit dependency just for assertThrows
, especially since I'm making my Jar distribution self-test when run, so the testing frameworks are inside it.
I'm currently using (Java):
try {
[Manipulate object "o"]
assertWithMessage("Manipulating %s should have thrown an UnsupportedOperationException", o).fail();
} catch (UnsupportedOperationException expected) {}
We'd like to use this code https://github.com/aosp-mirror/platform_frameworks_support/commit/bf04c31bd91bc6188abef45f7d9c1fa4040e5633#diff-46afb720089a0149afb46f71274f5642 from our Kotlin tests, can you please include it into Truth?
We could just add it to one of our internal libraries and use it. However, seeing as this code is being duplicated on many repos on GitHub: https://github.com/search?l=Kotlin&p=2&q=ThrowableSubject&type=Code, it might make sense to include it in Truth.