[MAGNOLIA-6092] Hamcrest UtilMatchers: a pattern for asserting an exception is thrown Created: 18/Feb/15 Updated: 22/May/15 Resolved: 12/May/15 |
|
| Status: | Closed |
| Project: | Magnolia |
| Component/s: | testing |
| Affects Version/s: | None |
| Fix Version/s: | 5.4 |
| Type: | New Feature | Priority: | Neutral |
| Reporter: | Magnolia International | Assignee: | Magnolia International |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||
| Template: |
|
||||||||||||||||
| Acceptance criteria: |
Empty
|
||||||||||||||||
| Date of First Response: | |||||||||||||||||
| Description |
|
In our current unit tests, we use a mixture of 2 patterns to assert the certain code throws certain exception:
@Test(expected = IllegalArgumentException.class)
public void testGetTitleThrowsException() {
new MetaData(root).getTitle();
}
@Test
public void testGetTitleThrowsException() {
try {
new MetaData(root).getTitle();
fail("should have failed");
} catch (Throwable t) {
// various assertions on t, possibly using info.magnolia.test.hamcrest.UtilMatchers
}
}
The former is concise, but leaves no place for signaling the intent of the test, and provides no way to check the actual exception; it's good enough in some cases, but in others, we really want to make sure we're getting the precise exception we think we're getting. The latter is much more precise, but is a tad verbose, maybe a bit difficult to read, and can be error prone (it's easy to forget the call to fail(), for example) I propose the following, implemented using a new matcher: import static info.magnolia.test.hamcrest.UtilMatchers.*; import static org.junit.Assert.*; import info.magnolia.test.hamcrest.Execution; ... @Test public void throwMatcherSampleUsage() { assertThat(new Execution(){ public void evaluate() throws Exception { // do something that fails, such as System.out.println(1/0); } }, throwMatcher(isExceptionWithMatchingMessage(ArithmeticException.class, "/ by zero"))); } or, slightly differently:
@Test
public void throwMatcherSampleUsage() {
final Execution shouldFail = new Execution() {
@Override
public void evaluate() throws Exception {
// do something that fails, such as
System.out.println(1 / 0);
}
};
assertThat(shouldFail, throwMatcher(isExceptionWithMatchingMessage(ArithmeticException.class, "/ by zero")));
}
Additionally, we can even have the same principle to assert that a piece of code does not throw any exception: assertThat(new Execution() { @Override public void evaluate() throws Exception { // yay } }, noExceptionThrown()); And here's a sample of how it'd look like if we used Java 8's lambdas:
assertThat(() -> System.out.print(1 / 0), throwsException(isExceptionWithMatchingMessage(ArithmeticException.class, "/ by zero")));
|
| Comments |
| Comment by Magnolia International [ 18/Feb/15 ] |
|
Pushed into branch feature/ |
| Comment by Michael Mühlebach [ 19/Feb/15 ] |
|
Would be really helpful. But I have an idea for a more generic matcher. assertThat(...., thrownIsOfInstance(ArithmeticException.class)
.hasMessageContaining("by zero")
.hasNoCause());
Of course beside hasMessageContaining(), hasMessage() hasMessageStartingWith(), hasMessageEndingWith() would make sense as well. |
| Comment by Jan Haderka [ 20/Feb/15 ] |
|
@Michael great idea. Care to update branch to add impl for this? |
| Comment by Magnolia International [ 25/Feb/15 ] |
|
| Comment by Magnolia International [ 25/Feb/15 ] |
|
Replaced usage of info.magnolia.test.Assertion by a specialized interface (easier to extract from core); added lambda sample. |
| Comment by Magnolia International [ 25/Feb/15 ] |
|
I would like to propose to split out further improvement on exception matching to another task; this concerns UtilMatchers.isExceptionWith* methods, which pre-existed this ticket. This ticket is about UtilMatchers.throwsException() and throwsNothing. |
| Comment by Magnolia International [ 12/May/15 ] |
|
Reopening - moving these matchers to ExecutionMatcher. |
| Comment by Magnolia International [ 12/May/15 ] |
|
Re-done on feature/exception-matchers- |
| Comment by Michael Mühlebach [ 21/May/15 ] |
|
Review comments:
ChainingMatcher
ExactTypeMatcher
ExceptionMatcher
ExecutionMatcher
|
| Comment by Magnolia International [ 21/May/15 ] |
|