1b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpackage org.junit.rules; 2b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 3b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport static org.hamcrest.CoreMatchers.instanceOf; 4b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport static org.junit.matchers.JUnitMatchers.both; 5b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport static org.junit.matchers.JUnitMatchers.containsString; 6b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.hamcrest.Description; 7b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.hamcrest.Matcher; 8b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.hamcrest.StringDescription; 9b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.Assert; 10b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.internal.matchers.TypeSafeMatcher; 11b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotimport org.junit.runners.model.Statement; 12b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 13b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot/** 14b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * The ExpectedException Rule allows in-test specification of expected exception 15b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * types and messages: 16b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * 17b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * <pre> 18b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * // These tests all pass. 19b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * public static class HasExpectedException { 20b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * @Rule 21b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * public ExpectedException thrown= ExpectedException.none(); 22b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * 23b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * @Test 24b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * public void throwsNothing() { 25b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * // no exception expected, none thrown: passes. 26b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * } 27b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * 28b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * @Test 29b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * public void throwsNullPointerException() { 30b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * thrown.expect(NullPointerException.class); 31b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * throw new NullPointerException(); 32b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * } 33b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * 34b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * @Test 35b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * public void throwsNullPointerExceptionWithMessage() { 36b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * thrown.expect(NullPointerException.class); 37b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * thrown.expectMessage("happened?"); 38b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * thrown.expectMessage(startsWith("What")); 39b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * throw new NullPointerException("What happened?"); 40b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * } 41b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * } 42b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * </pre> 43b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */ 44b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabotpublic class ExpectedException implements TestRule { 45b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot /** 46b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * @return a Rule that expects no exception to be thrown 47b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * (identical to behavior without this Rule) 48b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */ 49b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public static ExpectedException none() { 50b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot return new ExpectedException(); 51b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 52b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 53b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot private Matcher<Object> fMatcher= null; 54b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 55b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot private ExpectedException() { 56b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 57b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 58b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 59b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public Statement apply(Statement base, 60b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot org.junit.runner.Description description) { 61b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot return new ExpectedExceptionStatement(base); 62b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 63b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 64b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot /** 65b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * Adds {@code matcher} to the list of requirements for any thrown exception. 66b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */ 67b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot // Should be able to remove this suppression in some brave new hamcrest world. 68b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot @SuppressWarnings("unchecked") 69b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public void expect(Matcher<?> matcher) { 70b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot if (fMatcher == null) 71b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot fMatcher= (Matcher<Object>) matcher; 72b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot else 73b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot fMatcher= both(fMatcher).and(matcher); 74b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 75b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 76b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot /** 77b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * Adds to the list of requirements for any thrown exception that it 78b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * should be an instance of {@code type} 79b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */ 80b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public void expect(Class<? extends Throwable> type) { 81b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot expect(instanceOf(type)); 82b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 83b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 84b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot /** 85b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * Adds to the list of requirements for any thrown exception that it 86b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * should <em>contain</em> string {@code substring} 87b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */ 88b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public void expectMessage(String substring) { 89b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot expectMessage(containsString(substring)); 90b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 91b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 92b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot /** 93b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * Adds {@code matcher} to the list of requirements for the message 94b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot * returned from any thrown exception. 95b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot */ 96b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public void expectMessage(Matcher<String> matcher) { 97b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot expect(hasMessage(matcher)); 98b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 99b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 100b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot private class ExpectedExceptionStatement extends Statement { 101b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot private final Statement fNext; 102b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 103b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public ExpectedExceptionStatement(Statement base) { 104b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot fNext= base; 105b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 106b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 107b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot @Override 108b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public void evaluate() throws Throwable { 109b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot try { 110b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot fNext.evaluate(); 111b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } catch (Throwable e) { 112b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot if (fMatcher == null) 113b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot throw e; 114b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot Assert.assertThat(e, fMatcher); 115b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot return; 116b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 117b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot if (fMatcher != null) 118b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot throw new AssertionError("Expected test to throw " 119b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot + StringDescription.toString(fMatcher)); 120b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 121b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 122b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 123b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot private Matcher<Throwable> hasMessage(final Matcher<String> matcher) { 124b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot return new TypeSafeMatcher<Throwable>() { 125b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public void describeTo(Description description) { 126b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot description.appendText("exception with message "); 127b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot description.appendDescriptionOf(matcher); 128b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 129b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot 130b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot @Override 131b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot public boolean matchesSafely(Throwable item) { 132b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot return matcher.matches(item.getMessage()); 133b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 134b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot }; 135b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot } 136b3823db9f1192d8c81345740b3e65bd6738ba55bBrett Chabot} 137