package org.junit.tests.experimental.rules;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
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 java.util.LinkedList;
import java.util.List;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.internal.AssumptionViolatedException;
import org.junit.rules.TestName;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
public class TestRuleTest {
private static boolean wasRun;
public static class ExampleTest {
@Rule
public TestRule example = new TestRule() {
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
wasRun = true;
base.evaluate();
}
;
};
}
};
@Test
public void nothing() {
}
}
@Test
public void ruleIsIntroducedAndEvaluated() {
wasRun = false;
JUnitCore.runClasses(ExampleTest.class);
assertTrue(wasRun);
}
public static class BothKindsOfRule implements TestRule, org.junit.rules.MethodRule {
public int applications = 0;
public Statement apply(Statement base, FrameworkMethod method,
Object target) {
applications++;
return base;
}
public Statement apply(Statement base, Description description) {
applications++;
return base;
}
}
public static class OneFieldTwoKindsOfRule {
@Rule
public BothKindsOfRule both = new BothKindsOfRule();
@Test
public void onlyOnce() {
assertEquals(1, both.applications);
}
}
@Test
public void onlyApplyOnceEvenIfImplementsBothInterfaces() {
assertTrue(JUnitCore.runClasses(OneFieldTwoKindsOfRule.class).wasSuccessful());
}
public static class SonOfExampleTest extends ExampleTest {
}
@Test
public void ruleIsIntroducedAndEvaluatedOnSubclass() {
wasRun = false;
JUnitCore.runClasses(SonOfExampleTest.class);
assertTrue(wasRun);
}
private static int runCount;
public static class MultipleRuleTest {
private static class Increment implements TestRule {
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
runCount++;
base.evaluate();
}
;
};
}
}
@Rule
public TestRule incrementor1 = new Increment();
@Rule
public TestRule incrementor2 = new Increment();
@Test
public void nothing() {
}
}
@Test
public void multipleRulesAreRun() {
runCount = 0;
JUnitCore.runClasses(MultipleRuleTest.class);
assertEquals(2, runCount);
}
public static class NoRulesTest {
public int x;
@Test
public void nothing() {
}
}
@Test
public void ignoreNonRules() {
Result result = JUnitCore.runClasses(NoRulesTest.class);
assertEquals(0, result.getFailureCount());
}
private static String log;
public static class OnFailureTest {
@Rule
public TestRule watcher = new TestWatcher() {
@Override
protected void failed(Throwable e, Description description) {
log += description + " " + e.getClass().getSimpleName();
}
};
@Test
public void nothing() {
fail();
}
}
@Test
public void onFailure() {
log = "";
Result result = JUnitCore.runClasses(OnFailureTest.class);
assertEquals(String.format("nothing(%s) AssertionError", OnFailureTest.class.getName()), log);
assertEquals(1, result.getFailureCount());
}
public static class WatchmanTest {
private static String watchedLog;
@Rule
public TestRule watcher = new TestWatcher() {
@Override
protected void failed(Throwable e, Description description) {
watchedLog += description + " "
+ e.getClass().getSimpleName() + "\n";
}
@Override
protected void succeeded(Description description) {
watchedLog += description + " " + "success!\n";
}
};
@Test
public void fails() {
fail();
}
@Test
public void succeeds() {
}
}
@Test
public void succeeded() {
WatchmanTest.watchedLog = "";
JUnitCore.runClasses(WatchmanTest.class);
assertThat(WatchmanTest.watchedLog, containsString(String.format("fails(%s) AssertionError", WatchmanTest.class.getName())));
assertThat(WatchmanTest.watchedLog, containsString(String.format("succeeds(%s) success!", WatchmanTest.class.getName())));
}
public static class BeforesAndAfters {
private static StringBuilder watchedLog = new StringBuilder();
@Before
public void before() {
watchedLog.append("before ");
}
@Rule
public TestRule watcher = new LoggingTestWatcher(watchedLog);
@After
public void after() {
watchedLog.append("after ");
}
@Test
public void succeeds() {
watchedLog.append("test ");
}
}
@Test
public void beforesAndAfters() {
BeforesAndAfters.watchedLog = new StringBuilder();
JUnitCore.runClasses(BeforesAndAfters.class);
assertThat(BeforesAndAfters.watchedLog.toString(),
is("starting before test after succeeded finished "));
}
public static class WrongTypedField {
@Rule
public int x = 5;
@Test
public void foo() {
}
}
@Test
public void validateWrongTypedField() {
assertThat(testResult(WrongTypedField.class),
hasSingleFailureContaining("must implement MethodRule"));
}
public static class SonOfWrongTypedField extends WrongTypedField {
}
@Test
public void validateWrongTypedFieldInSuperclass() {
assertThat(testResult(SonOfWrongTypedField.class),
hasSingleFailureContaining("must implement MethodRule"));
}
public static class PrivateRule {
@Rule
private TestRule rule = new TestName();
@Test
public void foo() {
}
}
@Test
public void validatePrivateRule() {
assertThat(testResult(PrivateRule.class),
hasSingleFailureContaining("must be public"));
}
public static class CustomTestName implements TestRule {
public String name = null;
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
name = description.getMethodName();
base.evaluate();
}
};
}
}
public static class UsesCustomMethodRule {
@Rule
public CustomTestName counter = new CustomTestName();
@Test
public void foo() {
assertEquals("foo", counter.name);
}
}
@Test
public void useCustomMethodRule() {
assertThat(testResult(UsesCustomMethodRule.class), isSuccessful());
}
public static class MethodExampleTest {
private TestRule example = new TestRule() {
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
wasRun = true;
base.evaluate();
}
;
};
}
};
@Rule
public TestRule getExample() {
return example;
}
@Test
public void nothing() {
}
}
@Test
public void methodRuleIsIntroducedAndEvaluated() {
wasRun = false;
JUnitCore.runClasses(MethodExampleTest.class);
assertTrue(wasRun);
}
public static class MethodBothKindsOfRule implements TestRule, org.junit.rules.MethodRule {
public int applications = 0;
public Statement apply(Statement base, FrameworkMethod method,
Object target) {
applications++;
return base;
}
public Statement apply(Statement base, Description description) {
applications++;
return base;
}
}
public static class MethodOneFieldTwoKindsOfRule {
private MethodBothKindsOfRule both = new MethodBothKindsOfRule();
@Rule
public MethodBothKindsOfRule getBoth() {
return both;
}
@Test
public void onlyOnce() {
assertEquals(1, both.applications);
}
}
@Test
public void methodOnlyApplyOnceEvenIfImplementsBothInterfaces() {
assertTrue(JUnitCore.runClasses(MethodOneFieldTwoKindsOfRule.class).wasSuccessful());
}
public static class MethodSonOfExampleTest extends MethodExampleTest {
}
@Test
public void methodRuleIsIntroducedAndEvaluatedOnSubclass() {
wasRun = false;
JUnitCore.runClasses(MethodSonOfExampleTest.class);
assertTrue(wasRun);
}
// private static int runCount;
public static class MethodMultipleRuleTest {
private static class Increment implements TestRule {
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
runCount++;
base.evaluate();
}
;
};
}
}
private TestRule incrementor1 = new Increment();
@Rule
public TestRule getIncrementor1() {
return incrementor1;
}
private TestRule incrementor2 = new Increment();
@Rule
public TestRule getIncrementor2() {
return incrementor2;
}
@Test
public void nothing() {
}
}
@Test
public void methodMultipleRulesAreRun() {
runCount = 0;
JUnitCore.runClasses(MethodMultipleRuleTest.class);
assertEquals(2, runCount);
}
public static class MethodNoRulesTest {
public int x;
@Test
public void nothing() {
}
}
@Test
public void methodIgnoreNonRules() {
Result result = JUnitCore.runClasses(MethodNoRulesTest.class);
assertEquals(0, result.getFailureCount());
}
public static class MethodOnFailureTest {
private TestRule watchman = new TestWatcher() {
@Override
protected void failed(Throwable e, Description description) {
log += description + " " + e.getClass().getSimpleName();
}
};
@Rule
public TestRule getWatchman() {
return watchman;
}
@Test
public void nothing() {
fail();
}
}
@Test
public void methodOnFailure() {
log = "";
Result result = JUnitCore.runClasses(MethodOnFailureTest.class);
assertEquals(String.format("nothing(%s) AssertionError", MethodOnFailureTest.class.getName()), log);
assertEquals(1, result.getFailureCount());
}
public static class MethodOnSkippedTest {
private TestRule watchman = new TestWatcher() {
@Override
protected void skipped(AssumptionViolatedException e, Description description) {
log += description + " " + e.getClass().getSimpleName();
}
};
@Rule
public TestRule getWatchman() {
return watchman;
}
@Test
public void nothing() {
Assume.assumeTrue(false);
}
}
@Test
public void methodOnSkipped() {
log = "";
Result result = JUnitCore.runClasses(MethodOnSkippedTest.class);
assertEquals(String.format("nothing(%s) AssumptionViolatedException", MethodOnSkippedTest.class.getName()), log);
assertEquals(0, result.getFailureCount());
assertEquals(1, result.getRunCount());
}
public static class MethodWatchmanTest {
@SuppressWarnings("unused")
private static String watchedLog;
private TestRule watchman = new TestWatcher() {
@Override
protected void failed(Throwable e, Description description) {
watchedLog += description + " "
+ e.getClass().getSimpleName() + "\n";
}
@Override
protected void succeeded(Description description) {
watchedLog += description + " " + "success!\n";
}
};
@Rule
public TestRule getWatchman() {
return watchman;
}
@Test
public void fails() {
fail();
}
@Test
public void succeeds() {
}
}
@Test
public void methodSucceeded() {
WatchmanTest.watchedLog = "";
JUnitCore.runClasses(WatchmanTest.class);
assertThat(WatchmanTest.watchedLog, containsString(String.format("fails(%s) AssertionError", WatchmanTest.class.getName())));
assertThat(WatchmanTest.watchedLog, containsString(String.format("succeeds(%s) success!", WatchmanTest.class.getName())));
}
public static class MethodBeforesAndAfters {
private static String watchedLog;
@Before
public void before() {
watchedLog += "before ";
}
private TestRule watchman = new TestWatcher() {
@Override
protected void starting(Description d) {
watchedLog += "starting ";
}
@Override
protected void finished(Description d) {
watchedLog += "finished ";
}
@Override
protected void succeeded(Description d) {
watchedLog += "succeeded ";
}
};
@Rule
public TestRule getWatchman() {
return watchman;
}
@After
public void after() {
watchedLog += "after ";
}
@Test
public void succeeds() {
watchedLog += "test ";
}
}
@Test
public void methodBeforesAndAfters() {
MethodBeforesAndAfters.watchedLog = "";
JUnitCore.runClasses(MethodBeforesAndAfters.class);
assertThat(MethodBeforesAndAfters.watchedLog, is("starting before test after succeeded finished "));
}
public static class MethodWrongTypedField {
@Rule
public int getX() {
return 5;
}
@Test
public void foo() {
}
}
@Test
public void methodValidateWrongTypedField() {
assertThat(testResult(MethodWrongTypedField.class),
hasSingleFailureContaining("must return an implementation of MethodRule"));
}
public static class MethodSonOfWrongTypedField extends MethodWrongTypedField {
}
@Test
public void methodValidateWrongTypedFieldInSuperclass() {
assertThat(testResult(MethodSonOfWrongTypedField.class),
hasSingleFailureContaining("must return an implementation of MethodRule"));
}
public static class MethodPrivateRule {
@Rule
private TestRule getRule() {
return new TestName();
}
@Test
public void foo() {
}
}
@Test
public void methodValidatePrivateRule() {
assertThat(testResult(MethodPrivateRule.class),
hasSingleFailureContaining("must be public"));
}
public static class MethodUsesCustomMethodRule {
private CustomTestName counter = new CustomTestName();
@Rule
public CustomTestName getCounter() {
return counter;
}
@Test
public void foo() {
assertEquals("foo", counter.name);
}
}
@Test
public void methodUseCustomMethodRule() {
assertThat(testResult(MethodUsesCustomMethodRule.class), isSuccessful());
}
private static final List<String> orderList = new LinkedList<String>();
private static class OrderTestRule implements TestRule {
private String name;
public OrderTestRule(String name) {
this.name = name;
}
public Statement apply(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
orderList.add(name);
base.evaluate();
}
};
}
}
;
public static class UsesFieldAndMethodRule {
@Rule
public OrderTestRule orderMethod() {
return new OrderTestRule("orderMethod");
}
@Rule
public OrderTestRule orderField = new OrderTestRule("orderField");
@Test
public void foo() {
assertEquals("orderField", orderList.get(0));
assertEquals("orderMethod", orderList.get(1));
}
}
@Test
public void usesFieldAndMethodRule() {
orderList.clear();
assertThat(testResult(UsesFieldAndMethodRule.class), isSuccessful());
}
public static class MultipleCallsTest implements TestRule {
public int applications = 0;
public Statement apply(Statement base, Description description) {
applications++;
return base;
}
}
public static class CallMethodOnlyOnceRule {
int countOfMethodCalls = 0;
private static class Dummy implements TestRule {
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
base.evaluate();
}
;
};
}
}
@Rule
public Dummy both() {
countOfMethodCalls++;
return new Dummy();
}
@Test
public void onlyOnce() {
assertEquals(1, countOfMethodCalls);
}
}
@Test
public void testCallMethodOnlyOnceRule() {
assertTrue(JUnitCore.runClasses(CallMethodOnlyOnceRule.class).wasSuccessful());
}
}