package de.bechte.junit.runners.context.statements.builder; import de.bechte.junit.stubs.statements.rules.*; import org.hamcrest.FeatureMatcher; import org.hamcrest.Matcher; import org.junit.Test; import org.junit.runner.Description; import org.junit.runner.notification.RunNotifier; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.Statement; import org.junit.runners.model.TestClass; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; import static org.mockito.Mockito.mock; public class HierarchicalRunRulesStatementBuilderTest { private final Statement nextStatement = mock(Statement.class); private final RunNotifier runNotifier = mock(RunNotifier.class); private final FrameworkMethod frameworkMethod = mock(FrameworkMethod.class); private final HierarchicalRunRulesStatementBuilder hierarchicalRunRulesStatementBuilder = new HierarchicalRunRulesStatementBuilder(); @Test public void whenNoRulesArePresentInTestTheNextStatementRemainsUnwrapped() throws Exception { Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithoutRule.class), mock(FrameworkMethod.class), new TestWithoutRule(), nextStatement, Description.createTestDescription(TestWithoutRule.class, "Desc"), runNotifier); assertThat(statement, is(nextStatement)); } @Test public void testRulesAreAppliedForAllHierarchyLevels() throws Throwable { Description testDescription = Description.createTestDescription(TestWithTestRuleOnHighestLevel.class, "Test with TestRule"); CapturingTestRuleStub capturingTestRuleStub = new CapturingTestRuleStub(); TestWithTestRuleOnHighestLevel outer = new TestWithTestRuleOnHighestLevel(capturingTestRuleStub); Object target = TestWithTestRuleOnHighestLevel.Context.class.getConstructors()[0].newInstance(outer); Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithTestRuleOnHighestLevel.class), mock(FrameworkMethod.class), target, nextStatement, testDescription, runNotifier); assertThat(capturingTestRuleStub.getNumberOfApplications(), is(2)); assertThat(capturingTestRuleStub.getApplyMethodParameters(), everyItem(descriptionTestRuleApplyWasCalledWith(equalTo(testDescription)))); assertThat(capturingTestRuleStub.getApplyMethodParameters(), contains(statementTestRuleApplyWasCalledWith(equalTo(nextStatement)), statementTestRuleApplyWasCalledWith(notNullValue(Statement.class)))); statement.evaluate(); assertThat(capturingTestRuleStub.statementReturnedByRuleApplyMethodWasEvaluated(), is(true)); } @Test public void testRulesAreNotAppliedForHierarchiesAboveTheirPlaceOfDefinition() throws Throwable { Description testDescription = Description.createTestDescription(TestWithTestRuleOnLowerLevel.class, "Test with TestRule"); CapturingTestRuleStub capturingTestRuleStub = new CapturingTestRuleStub(); TestWithTestRuleOnLowerLevel outer = new TestWithTestRuleOnLowerLevel(); Object target = TestWithTestRuleOnLowerLevel.Context.class.getConstructors()[0].newInstance(outer, capturingTestRuleStub); Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithTestRuleOnHighestLevel.class), mock(FrameworkMethod.class), target, nextStatement, testDescription, runNotifier); assertThat(capturingTestRuleStub.getNumberOfApplications(), is(1)); assertThat(capturingTestRuleStub.getApplyMethodParameters(), contains(descriptionTestRuleApplyWasCalledWith(equalTo(testDescription)))); assertThat(capturingTestRuleStub.getApplyMethodParameters(), contains(statementTestRuleApplyWasCalledWith(equalTo(nextStatement)))); statement.evaluate(); assertThat(capturingTestRuleStub.statementReturnedByRuleApplyMethodWasEvaluated(), is(true)); } @Test public void methodRuleIsPresentOnHighestLevelAndTestClassHasNoInnerContexts() throws Throwable { Description testDescription = Description.createTestDescription(TestWithMethodRuleOnHighestLevelWithoutInnerContexts.class, "Test with MethodRule"); CapturingMethodRuleStub capturingMethodRuleStub = new CapturingMethodRuleStub(); Object target = new TestWithMethodRuleOnHighestLevelWithoutInnerContexts(capturingMethodRuleStub); Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithMethodRuleOnHighestLevelWithoutInnerContexts.class), frameworkMethod, target, nextStatement, testDescription, runNotifier); assertThat(capturingMethodRuleStub.getNumberOfApplications(), is(1)); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(targetCalledWith(target))); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(frameworkMethodCalledWith(frameworkMethod))); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(statementCalledWith(nextStatement))); statement.evaluate(); assertThat(capturingMethodRuleStub.statementReturnedByRuleApplyMethodWasEvaluated(), is(true)); } @Test public void whenRuleImplementsBothTestRuleAndMethodRule_onlyTestRuleApplyIsExecuted() throws Throwable { Description testDescription = Description.createTestDescription(TestWithRuleThatImplementsBothTestRuleAndMethodRule.class, "Test with rule that implements both TestRule and MethodRule"); CapturingTestAndMethodRuleStub capturingTestAndMethodRuleStub = new CapturingTestAndMethodRuleStub(); Object target = new TestWithRuleThatImplementsBothTestRuleAndMethodRule(capturingTestAndMethodRuleStub); Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithRuleThatImplementsBothTestRuleAndMethodRule.class), frameworkMethod, target, nextStatement, testDescription, runNotifier); assertThat(capturingTestAndMethodRuleStub.getNumberOfApplicationsOfTestRulesApplyMethod(), is(1)); assertThat(capturingTestAndMethodRuleStub.getStatementTestRuleApplyWasCalledWith(), is(nextStatement)); assertThat(capturingTestAndMethodRuleStub.getDescriptionTestRuleApplyWasCalledWith(), is(testDescription)); statement.evaluate(); assertThat(capturingTestAndMethodRuleStub.statementReturnedByRuleApplyMethodWasEvaluated(), is(true)); } @Test public void methodRuleIsAppliedForEachHierarchy() throws Throwable { CapturingMethodRuleStub capturingMethodRuleStub = new CapturingMethodRuleStub(); TestWithMethodRuleAndTwoHierarchies outer = new TestWithMethodRuleAndTwoHierarchies(capturingMethodRuleStub); Object target = TestWithMethodRuleAndTwoHierarchies.Context.class.getConstructors()[0].newInstance(outer); Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithMethodRuleAndTwoHierarchies.class), frameworkMethod, target, nextStatement, Description.createTestDescription(TestWithMethodRuleAndTwoHierarchies.class, "Test with MethodRule and hierarchies"), runNotifier); assertThat(capturingMethodRuleStub.getNumberOfApplications(), is(2)); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), everyItem(frameworkMethodCalledWith(frameworkMethod))); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(statementCalledWith(nextStatement), statementCalledWith(notNullValue(Statement.class)))); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(targetCalledWith(target), targetCalledWith(instanceOf(TestWithMethodRuleAndTwoHierarchies.class)))); statement.evaluate(); assertThat(capturingMethodRuleStub.statementReturnedByRuleApplyMethodWasEvaluated(), is(true)); } @Test public void methodRulesAreNotAppliedForHierarchiesAboveTheirPlaceOfDefinition() throws Throwable { Description testDescription = Description.createTestDescription(TestWithMethodRuleOnLowerLevel.class, "Test with TestRule"); CapturingMethodRuleStub capturingMethodRuleStub = new CapturingMethodRuleStub(); TestWithMethodRuleOnLowerLevel outer = new TestWithMethodRuleOnLowerLevel(); Object target = TestWithMethodRuleOnLowerLevel.Context.class.getConstructors()[0].newInstance(outer, capturingMethodRuleStub); Statement statement = hierarchicalRunRulesStatementBuilder.createStatement(new TestClass(TestWithTestRuleOnHighestLevel.class), mock(FrameworkMethod.class), target, nextStatement, testDescription, runNotifier); assertThat(capturingMethodRuleStub.getNumberOfApplications(), is(1)); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(statementCalledWith(equalTo(nextStatement)))); assertThat(capturingMethodRuleStub.getApplyInvocationParameters(), contains(targetCalledWith(target))); statement.evaluate(); assertThat(capturingMethodRuleStub.statementReturnedByRuleApplyMethodWasEvaluated(), is(true)); } private Matcher<CapturingMethodRuleStub.ApplyInvocationParameter> targetCalledWith(Object target) { return targetCalledWith(equalTo(target)); } private Matcher<CapturingMethodRuleStub.ApplyInvocationParameter> targetCalledWith(Matcher<Object> submatcher) { return new FeatureMatcher<CapturingMethodRuleStub.ApplyInvocationParameter, Object>(submatcher, "target", "target") { @Override protected Object featureValueOf(CapturingMethodRuleStub.ApplyInvocationParameter actual) { return actual.getTargetApplyWasCalledWith(); } }; } private Matcher<CapturingMethodRuleStub.ApplyInvocationParameter> statementCalledWith(Statement statement) { return statementCalledWith(equalTo(statement)); } private Matcher<CapturingMethodRuleStub.ApplyInvocationParameter> statementCalledWith(Matcher<Statement> submatcher) { return new FeatureMatcher<CapturingMethodRuleStub.ApplyInvocationParameter, Statement>(submatcher, "statement", "statement") { @Override protected Statement featureValueOf(CapturingMethodRuleStub.ApplyInvocationParameter actual) { return actual.getStatementApplyWasCalledWith(); } }; } private Matcher<CapturingMethodRuleStub.ApplyInvocationParameter> frameworkMethodCalledWith(FrameworkMethod frameworkMethod) { return new FeatureMatcher<CapturingMethodRuleStub.ApplyInvocationParameter, FrameworkMethod>(equalTo(frameworkMethod), "framework method", "method") { @Override protected FrameworkMethod featureValueOf(CapturingMethodRuleStub.ApplyInvocationParameter actual) { return actual.getFrameworkMethodApplyWasCalledWith(); } }; } private Matcher<CapturingTestRuleStub.ApplyMethodParameter> statementTestRuleApplyWasCalledWith(Matcher<Statement> submatcher) { return new FeatureMatcher<CapturingTestRuleStub.ApplyMethodParameter, Statement>(submatcher, "statement", "statement") { @Override protected Statement featureValueOf(CapturingTestRuleStub.ApplyMethodParameter actual) { return actual.getStatementAppliedWasCalledWith(); } }; } private Matcher<CapturingTestRuleStub.ApplyMethodParameter> descriptionTestRuleApplyWasCalledWith(Matcher<Description> submatcher) { return new FeatureMatcher<CapturingTestRuleStub.ApplyMethodParameter, Description>(submatcher, "description", "description") { @Override protected Description featureValueOf(CapturingTestRuleStub.ApplyMethodParameter actual) { return actual.getDescriptionApplyWasCalledWith(); } }; } }