Skip to content

Commit

Permalink
ExpectedException drastically simplified
Browse files Browse the repository at this point in the history
Signed-off-by: Kent Beck <kent@threeriversinstitute.org>
  • Loading branch information
David Saff authored and KentBeck committed Jun 2, 2009
1 parent 3f05aac commit a423117
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 45 deletions.
@@ -1,30 +1,36 @@
package org.junit.experimental.interceptor;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import org.hamcrest.FeatureMatcher;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
import org.junit.Assert;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

public class ExpectedException implements StatementInterceptor {
private Class<? extends Throwable> fType;
private String fMessage;
private Matcher<Throwable> fMatcher= null;

public Statement intercept(Statement base, FrameworkMethod method) {
return new ExpectedExceptionStatement(base);
}

// TODO (Jun 1, 2009 3:56:50 PM): expect multiple things
// TODO (Jun 1, 2009 4:26:59 PM): expect on original throwable
public void expect(Class<? extends Throwable> type) {
fType= type;
fMatcher= instanceOf(type);
}

public void expectMessage(String message) {
fMessage= message;
public void expectMessage(String substring) {
expectMessage(containsString(substring));
}

private boolean noExpectedException() {
return fType == null && fMessage == null;
public void expectMessage(Matcher<String> matcher) {
fMatcher= hasMessage(matcher);
}

public class ExpectedExceptionStatement extends Statement {

private class ExpectedExceptionStatement extends Statement {
private final Statement fNext;

public ExpectedExceptionStatement(Statement base) {
Expand All @@ -33,42 +39,27 @@ public ExpectedExceptionStatement(Statement base) {

@Override
public void evaluate() throws Throwable {
boolean complete = false;
try {
fNext.evaluate();
complete = true;
} catch (Throwable e) {
if (noExpectedException())
if (fMatcher == null)
throw e;
// TODO (May 26, 2009 11:46:31 PM): isInstance?
if (fType != null && !fType.isAssignableFrom(e.getClass())) {
String message= "Unexpected exception, expected<"
+ fType.getName() + "> but was<"
+ e.getClass().getName() + ">";
throw new Exception(message, e);
}
if (fMessage != null && !getMessage(e).contains(fMessage)) {
String message= "Unexpected exception message, expected<"
+ fMessage + "> but was<"
+ getMessage(e) + ">";
throw new Exception(message, e);
}
}
// TODO (May 26, 2009 11:54:22 PM): do I need complete
if (complete && !noExpectedException()) {
if (fType != null)
throw new AssertionError("Expected exception: "
+ fType.getName());
else if (fMessage != null)
throw new AssertionError("Expected exception with message: "
+ fMessage);
else
throw new RuntimeException("How'd we get here?");
Assert.assertThat(e, fMatcher);
return;
}
if (fMatcher != null)
throw new AssertionError("Expected test to throw "
+ StringDescription.toString(fMatcher));
}
}

private String getMessage(Throwable e) {
return e.getMessage() == null ? "" : e.getMessage();
}
private Matcher<Throwable> hasMessage(Matcher<String> matcher) {
return new FeatureMatcher<Throwable, String>(matcher,
"exception with message", "getMessage()") {
@Override
protected String featureValueOf(Throwable actual) {
return actual.getMessage();
}
};
}
}
Expand Up @@ -5,7 +5,6 @@

import org.junit.runners.model.Statement;


public class ExpectException extends Statement {
private Statement fNext;
private final Class<? extends Throwable> fExpected;
Expand Down
@@ -1,12 +1,15 @@
package org.junit.tests.experimental.interceptor;

import static org.hamcrest.CoreMatchers.startsWith;
import static org.junit.Assert.assertThat;
import static org.junit.experimental.results.PrintableResult.testResult;
import static org.junit.experimental.results.ResultMatchers.hasSingleFailureContaining;
import static org.junit.experimental.results.ResultMatchers.isSuccessful;
import org.junit.Test;
import org.junit.experimental.interceptor.ExpectedException;
import org.junit.experimental.interceptor.Interceptor;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;

public class ExpectedExceptionInterceptorTest {
public static class HasExpectedException {
Expand Down Expand Up @@ -52,7 +55,7 @@ public void throwsNullPointerException() {
public void unExpectedExceptionFails() {
assertThat(
testResult(HasWrongExpectedException.class),
hasSingleFailureContaining("Unexpected exception, expected<java.lang.NullPointerException> but was<java.lang.IllegalArgumentException>"));
hasSingleFailureContaining("Expected: an instance of java.lang.NullPointerException"));
}

public static class HasWrongMessage {
Expand All @@ -70,7 +73,7 @@ public void throwsNullPointerException() {
public void wrongMessageFails() {
assertThat(
testResult(HasWrongMessage.class),
hasSingleFailureContaining("Unexpected exception message, expected<expectedMessage> but was<actualMessage>"));
hasSingleFailureContaining("\"expectedMessage\"\n but: getMessage() was \"actualMessage\""));
}

public static class WronglyExpectsException {
Expand All @@ -87,7 +90,7 @@ public void doesntThrowNullPointerException() {
public void failsIfExceptionNeverComes() {
assertThat(
testResult(WronglyExpectsException.class),
hasSingleFailureContaining("Expected exception: java.lang.NullPointerException"));
hasSingleFailureContaining("Expected test to throw an instance of java.lang.NullPointerException"));
}

public static class WronglyExpectsExceptionMessage {
Expand All @@ -104,7 +107,7 @@ public void doesntThrowAnything() {
public void failsIfExceptionMessageNeverComes() {
assertThat(
testResult(WronglyExpectsExceptionMessage.class),
hasSingleFailureContaining("Expected exception with message: anything!"));
hasSingleFailureContaining("Expected test to throw exception with message a string containing \"anything!\""));
}

public static class ExpectsSubstring {
Expand Down Expand Up @@ -139,6 +142,39 @@ public void throwsMore() {
public void failsWithNullExceptionMessage() {
assertThat(
testResult(ExpectsSubstringNullMessage.class),
hasSingleFailureContaining("Unexpected exception message, expected<anything!> but was<>"));
hasSingleFailureContaining("but: getMessage() was null"));
}

public static class ExpectsMatcher {
@Interceptor
public ExpectedException thrown= new ExpectedException();

@Test
public void throwsMore() {
thrown.expectMessage(startsWith("Ack"));
throw new NullPointerException("Ack!");
}
}

@Test
public void succeedsWithMatcher() {
assertThat(testResult(ExpectsMatcher.class), isSuccessful());
}

public static class ExpectsMatcherFails {
@Interceptor
public ExpectedException thrown= new ExpectedException();

@Test
public void throwsMore() {
thrown.expectMessage(startsWith("Wrong start"));
throw new NullPointerException("Back!");
}
}

@Test
public void failsWithMatcher() {
assertThat(testResult(ExpectsMatcherFails.class),
hasSingleFailureContaining("Wrong start"));
}
}

0 comments on commit a423117

Please sign in to comment.