Add message element to @Test?

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Add message element to @Test?

nick.radov
Would it make sense to enhance the @Test annotation with a new optional message element? Currently all of the Assert methods have overloaded forms including a message parameter in order to report what went wrong in human readable terms. However when you use the @Test annotation with an expected element to check that a particular exception was thrown there's no way to report a custom message back to the user.

http://junit.org/junit4/javadoc/latest/org/junit/Test.html#expected()

Alternatively, could we add a method to the ExpectedException rule to set a custom failure message?

http://junit.org/junit4/javadoc/latest/org/junit/rules/ExpectedException.html
Reply | Threaded
Open this post in threaded view
|

Re: Add message element to @Test?

Kevin Cooney ☕
Short version: use assertThrows().

I would recommend against using the 'expected' parameter of @Test. It only
allows you to assert that there exists some code in the test method that
throws an exception of the given type. The test can pass for the wrong
reason. Also, there's no way to make assertions on the exception message or
exception cause when you use @Test(expected = MyException.class).

I would also recommend against ExpectedException. I've seen to many cases
where it was used incorrectly (either doing validation after the method
that is expected to throw, or using ExpectedException inside of helper
method).

In JUnit 4.13 and JUnit 5, you will be able to use assertThrows() instead,
which allows the test to isolate what part of the test method is expected
to throw:

@Test
public void popWithEmptyStackShouldThrow() {
  Stack stack = new Stack();
  assertThrows(EmptyStackException.class, () -> stack.pop());
}

Note that the JUnit 5 versions of assertThrows() allows you to specify a
message or a supplier for a message. We didn't add a way to specify a
message in JUnit 4.13; we could add it, but I've seen some large teams use
assertThrows() and no one has asked for a way to customize the exception
message.

For JUnit 4.12 and below, I recommend good 'ol try...catch

The only safe use cases I see for the 'expected' parameter of @Test are
when the only thing the test method does is call a single method that is
expected to throw. In that case, you can use 'expected' and just give the
test method a readable name:

private final MyObject myObject = new MyObject();

@Test(expected = NullPointerException.class)
public void doSomething_paramMustNotBeNull() {
  myObject.doSomething(null);
}

That being said, once you get used to lambdas, the assertThrows() version
is very readable:

@Test
public void doSomething_paramMustNotBeNull() {
  assertThrows(
      NullPointerException.class, () -> myObject.doSomething(null));
}

-- Kevin

On Thu, Aug 31, 2017 at 10:13 AM, [hidden email] [junit] <
[hidden email]> wrote:

>
>
> Would it make sense to enhance the @Test annotation with a new optional
> message element? Currently all of the Assert methods have overloaded forms
> including a message parameter in order to report what went wrong in human
> readable terms. However when you use the @Test annotation with an expected
> element to check that a particular exception was thrown there's no way to
> report a custom message back to the user.
>
> http://junit.org/junit4/javadoc/latest/org/junit/Test.html#expected()
>
> Alternatively, could we add a method to the ExpectedException rule to set
> a custom failure message?
>
> http://junit.org/junit4/javadoc/latest/org/junit/
> rules/ExpectedException.html
>
>