001 package org.junit.rules;
002
003 import static org.junit.Assert.assertThat;
004 import static org.junit.Assert.assertThrows;
005
006 import java.util.ArrayList;
007 import java.util.List;
008 import java.util.concurrent.Callable;
009
010 import org.junit.function.ThrowingRunnable;
011 import org.junit.internal.AssumptionViolatedException;
012 import org.hamcrest.Matcher;
013 import org.junit.runners.model.MultipleFailureException;
014
015 /**
016 * The ErrorCollector rule allows execution of a test to continue after the
017 * first problem is found (for example, to collect _all_ the incorrect rows in a
018 * table, and report them all at once):
019 *
020 * <pre>
021 * public static class UsesErrorCollectorTwice {
022 * @Rule
023 * public ErrorCollector collector= new ErrorCollector();
024 *
025 * @Test
026 * public void example() {
027 * collector.addError(new Throwable("first thing went wrong"));
028 * collector.addError(new Throwable("second thing went wrong"));
029 * collector.checkThat(getResult(), not(containsString("ERROR!")));
030 * // all lines will run, and then a combined failure logged at the end.
031 * }
032 * }
033 * </pre>
034 *
035 * @since 4.7
036 */
037 public class ErrorCollector extends Verifier {
038 private List<Throwable> errors = new ArrayList<Throwable>();
039
040 @Override
041 protected void verify() throws Throwable {
042 MultipleFailureException.assertEmpty(errors);
043 }
044
045 /**
046 * Adds a Throwable to the table. Execution continues, but the test will fail at the end.
047 */
048 public void addError(Throwable error) {
049 if (error == null) {
050 throw new NullPointerException("Error cannot be null");
051 }
052 if (error instanceof AssumptionViolatedException) {
053 AssertionError e = new AssertionError(error.getMessage());
054 e.initCause(error);
055 errors.add(e);
056 } else {
057 errors.add(error);
058 }
059 }
060
061 /**
062 * Adds a failure to the table if {@code matcher} does not match {@code value}.
063 * Execution continues, but the test will fail at the end if the match fails.
064 *
065 * @deprecated use {@code org.hamcrest.junit.ErrorCollector.checkThat()}
066 */
067 @Deprecated
068 public <T> void checkThat(final T value, final Matcher<T> matcher) {
069 checkThat("", value, matcher);
070 }
071
072 /**
073 * Adds a failure with the given {@code reason}
074 * to the table if {@code matcher} does not match {@code value}.
075 * Execution continues, but the test will fail at the end if the match fails.
076 *
077 * @deprecated use {@code org.hamcrest.junit.ErrorCollector.checkThat()}
078 */
079 @Deprecated
080 public <T> void checkThat(final String reason, final T value, final Matcher<T> matcher) {
081 checkSucceeds(new Callable<Object>() {
082 public Object call() throws Exception {
083 assertThat(reason, value, matcher);
084 return value;
085 }
086 });
087 }
088
089 /**
090 * Adds to the table the exception, if any, thrown from {@code callable}.
091 * Execution continues, but the test will fail at the end if
092 * {@code callable} threw an exception.
093 */
094 public <T> T checkSucceeds(Callable<T> callable) {
095 try {
096 return callable.call();
097 } catch (AssumptionViolatedException e) {
098 AssertionError error = new AssertionError("Callable threw AssumptionViolatedException");
099 error.initCause(e);
100 addError(error);
101 return null;
102 } catch (Throwable e) {
103 addError(e);
104 return null;
105 }
106 }
107
108 /**
109 * Adds a failure to the table if {@code runnable} does not throw an
110 * exception of type {@code expectedThrowable} when executed.
111 * Execution continues, but the test will fail at the end if the runnable
112 * does not throw an exception, or if it throws a different exception.
113 *
114 * @param expectedThrowable the expected type of the exception
115 * @param runnable a function that is expected to throw an exception when executed
116 * @since 4.13
117 */
118 public void checkThrows(Class<? extends Throwable> expectedThrowable, ThrowingRunnable runnable) {
119 try {
120 assertThrows(expectedThrowable, runnable);
121 } catch (AssertionError e) {
122 addError(e);
123 }
124 }
125
126 }