Skip to content

Commit

Permalink
Match expected exception by type or subtype. Also, allow @ExpectedExc…
Browse files Browse the repository at this point in the history
…eption to be used with **no** message predicate
  • Loading branch information
glytching committed Feb 8, 2018
1 parent 5b8f957 commit 0dd9a1c
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 10 deletions.
33 changes: 32 additions & 1 deletion docs/expectedException.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ Note: these are all case sensitive.

#### Examples

###### Expect a Throwable, with no expectation on the exception message

```
@Test
@ExpectedException(type = Throwable.class)
public void canHandleAThrowable() throws Throwable {
throw new Throwable("...");
}
```
###### Expect a Throwable with an exact match on the exception message

```
Expand Down Expand Up @@ -65,4 +74,26 @@ public void canHandleAnExceptionWithAMessageWhichStartsWith() {
public void canHandleAnExceptionWithAMessageWhichContains() {
throw new MyDomainException("Terribly sorry old chap");
}
```
```

Notes:

Since usage of this extension implies that the developer _expects_ an exception to be thrown the following test case will fail since it throws no exception:

```
@Test
@ExpectedException(type = Throwable.class)
public void failsTestForMissingException() {}
```

The expected exception type will match on the given type and on any subclasses of that type. In other words, the following test will pass:

```
@Test
@ExpectedException(type = Throwable.class, messageIs = "Boom!")
public void canHandleAThrowable() throws Throwable {
throw new Exception("Boom!");
}
```

This is for consistency with JUnit Jupiter, in which `AssertThrows` matches an exception type or any subclass of that exception type.
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,30 @@
* }
* </pre>
*
* Note: since usage of this extension implies that the developer <i>expects</i> an exception to be
* thrown the following test case will fail since it throws no exception:
* Notes:
*
* <pre>
* <ul>
* <li>Since usage of this extension implies that the developer <i>expects</i> an exception to be
* thrown the following test case will fail since it throws no exception:
* <pre>
* &#064;Test
* &#064;ExpectedException(type = Throwable.class)
* public void failsTestForMissingException() {}
* </pre>
*
* This is to avoid a false positive where a test is declared to expect an exception and passes even
* if no exception is thrown.
* This is to avoid a false positive where a test is declared to expect an exception and
* passes even if no exception is thrown.
* <li>The expected exception type will match on the given type and any subclasses of that type.
* In other words, the following test will pass:
* <pre>
* &#064;Test
* &#064;ExpectedException(type = Throwable.class, messageIs = "Boom!")
* public void canHandleAThrowable() throws Throwable {
* throw new Exception("Boom!");
* }
* </pre>
* This is for consistency with JUnit Jupiter, in which <code>AssertThrows</code> matches an
* exception type or any subclass of that exception type.
* </ul>
*
* @see <a href="https://github.com/junit-team/junit4/wiki/Rules#expectedexception-rules">JUnit 4
* ExpectedException Rule</a>
Expand Down Expand Up @@ -101,7 +114,8 @@ public void handleTestExecutionException(ExtensionContext extensionContext, Thro
if (optional.isPresent()) {

ExpectedException annotation = optional.get();
if (throwable.getClass() == annotation.type()) {
// see https://github.com/glytching/junit-extensions/issues/5
if (annotation.type().isAssignableFrom(throwable.getClass())) {
if (where(function, getPredicate(annotation)).test(throwable)) {
getStore(extensionContext, this.getClass()).put(KEY, true);

Expand Down Expand Up @@ -145,9 +159,11 @@ private Predicate<String> getPredicate(ExpectedException annotation) {
return s -> s.startsWith(annotation.messageStartsWith());
} else if (has(annotation.messageContains())) {
return s -> s.contains(annotation.messageContains());
} else if (has(annotation.messageIs())) {
return s -> s.equals(annotation.messageIs());
} else {
// the default
return s -> s.equals(annotation.messageIs());
return s -> true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ public void canHandleAThrowable() throws Throwable {
throw new Throwable("Boom!");
}

@Test
@ExpectedException(type = Throwable.class, messageIs = "Boom!")
public void canHandleASubClassOfTheExpectedExceptionType() throws Throwable {
throw new Exception("Boom!");
}

@Test
@ExpectedException(type = Exception.class)
public void canHandleAnExceptionWithAnyMessage() throws Throwable {
throw new Exception("some message");
}

@Test
@ExpectedException(type = Exception.class, messageIs = "Boom!")
public void canHandleAnException() throws Exception {
Expand All @@ -49,4 +61,4 @@ public void canHandleAnExceptionWithAMessageWhichStartsWith() {
public void canHandleAnExceptionWithAMessageWhichContains() {
throw new RuntimeException("Terribly sorry old chap");
}
}
}

0 comments on commit 0dd9a1c

Please sign in to comment.