package com.tngtech.archunit.junit; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.junit.ArchUnitRunner.SharedCache; import com.tngtech.archunit.lang.ArchRule; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.Description; import org.junit.runner.notification.Failure; import org.junit.runner.notification.RunNotifier; import org.junit.runners.model.InitializationError; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import static com.tngtech.archunit.core.domain.TestUtils.javaClassesViaReflection; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.IgnoredArchTest.RULE_ONE_IN_IGNORED_TEST; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.IgnoredArchTest.RULE_TWO_IN_IGNORED_TEST; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.SomeArchTest.FAILING_FIELD_NAME; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.SomeArchTest.IGNORED_FIELD_NAME; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.SomeArchTest.SATISFIED_FIELD_NAME; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.WrongArchTestWrongFieldType.NO_RULE_AT_ALL_FIELD_NAME; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsRuleFieldsTest.WrongArchTestWrongModifier.WRONG_MODIFIER_FIELD_NAME; import static com.tngtech.archunit.junit.ArchUnitRunnerTestUtils.BE_SATISFIED; import static com.tngtech.archunit.junit.ArchUnitRunnerTestUtils.NEVER_BE_SATISFIED; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.all; import static com.tngtech.archunit.lang.syntax.ClassesIdentityTransformer.classes; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ArchUnitRunnerRunsRuleFieldsTest { @Rule public final ExpectedException thrown = ExpectedException.none(); @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private SharedCache cache; @Mock private ClassCache classCache; @Mock private RunNotifier runNotifier; @Captor private ArgumentCaptor<Description> descriptionCaptor; @Captor private ArgumentCaptor<Failure> failureCaptor; @InjectMocks private ArchUnitRunner runner = ArchUnitRunnerTestUtils.newRunnerFor(SomeArchTest.class); private JavaClasses cachedClasses = javaClassesViaReflection(Object.class); @Before public void setUp() { when(cache.get()).thenReturn(classCache); when(classCache.getClassesToAnalyzeFor(any(Class.class))).thenReturn(cachedClasses); } @Test public void should_find_children() throws Exception { assertThat(runner.getChildren()).as("Rules defined in Test Class").hasSize(3); } @Test public void should_start_rule() { ArchTestExecution satisfiedRule = getRule(SATISFIED_FIELD_NAME); runner.runChild(satisfiedRule, runNotifier); verify(runNotifier).fireTestStarted(descriptionCaptor.capture()); assertThat(descriptionCaptor.getValue().toString()).contains(SATISFIED_FIELD_NAME); } @Test public void should_accept_satisfied_rule() { ArchTestExecution satisfiedRule = getRule(SATISFIED_FIELD_NAME); runner.runChild(satisfiedRule, runNotifier); verify(runNotifier, never()).fireTestFailure(any(Failure.class)); verify(runNotifier).fireTestFinished(descriptionCaptor.capture()); assertThat(descriptionCaptor.getValue().toString()).contains(SATISFIED_FIELD_NAME); } @Test public void should_fail_on_wrong_field_visibility() throws InitializationError { ArchUnitRunner runner = new ArchUnitRunner(WrongArchTestWrongModifier.class); thrown.expectMessage("With @ArchTest annotated members must be public and static"); runner.runChild(ArchUnitRunnerTestUtils.getRule(WRONG_MODIFIER_FIELD_NAME, runner), runNotifier); } @Test public void should_fail_on_wrong_field_type() throws InitializationError { ArchUnitRunner runner = new ArchUnitRunner(WrongArchTestWrongFieldType.class); runner.runChild(ArchUnitRunnerTestUtils.getRule(NO_RULE_AT_ALL_FIELD_NAME, runner), runNotifier); verify(runNotifier).fireTestFailure(failureCaptor.capture()); assertThat(failureCaptor.getValue().getMessage()) .contains("Only fields of type ArchRule may be annotated with @ArchTest"); } @Test public void should_fail_unsatisfied_rule() { ArchTestExecution satisfiedRule = getRule(FAILING_FIELD_NAME); runner.runChild(satisfiedRule, runNotifier); verify(runNotifier).fireTestFailure(failureCaptor.capture()); Failure failure = failureCaptor.getValue(); assertThat(failure.getDescription().toString()).contains(FAILING_FIELD_NAME); assertThat(failure.getException()).isInstanceOf(AssertionError.class); } @Test public void should_skip_ignored_rule() { ArchTestExecution satisfiedRule = getRule(IGNORED_FIELD_NAME); runner.runChild(satisfiedRule, runNotifier); verify(runNotifier).fireTestIgnored(descriptionCaptor.capture()); assertThat(descriptionCaptor.getValue().toString()).contains(IGNORED_FIELD_NAME); } @Test public void should_skip_ignored_test() throws InitializationError { ArchUnitRunner runner = new ArchUnitRunner(IgnoredArchTest.class); runner.runChild(ArchUnitRunnerTestUtils.getRule(RULE_ONE_IN_IGNORED_TEST, runner), runNotifier); runner.runChild(ArchUnitRunnerTestUtils.getRule(RULE_TWO_IN_IGNORED_TEST, runner), runNotifier); verify(runNotifier, times(2)).fireTestIgnored(descriptionCaptor.capture()); assertThat(descriptionCaptor.getAllValues()).extractingResultOf("getMethodName") .contains(RULE_ONE_IN_IGNORED_TEST, RULE_TWO_IN_IGNORED_TEST); } private ArchTestExecution getRule(String name) { return ArchUnitRunnerTestUtils.getRule(name, runner); } @AnalyzeClasses(packages = "some.pkg") public static class SomeArchTest { static final String SATISFIED_FIELD_NAME = "someSatisfiedRule"; static final String FAILING_FIELD_NAME = "someFailingRule"; static final String IGNORED_FIELD_NAME = "someIgnoredRule"; @ArchTest public static final ArchRule someSatisfiedRule = all(classes()).should(BE_SATISFIED); @ArchTest public static final ArchRule someFailingRule = all(classes()).should(NEVER_BE_SATISFIED); @ArchIgnore @ArchTest public static final ArchRule someIgnoredRule = all(classes()).should(NEVER_BE_SATISFIED); } @AnalyzeClasses(packages = "some.pkg") public static class WrongArchTestWrongModifier { static final String WRONG_MODIFIER_FIELD_NAME = "ruleWithWrongModifier"; @ArchTest private ArchRule ruleWithWrongModifier = all(classes()).should(BE_SATISFIED); } @AnalyzeClasses(packages = "some.pkg") public static class WrongArchTestWrongFieldType { static final String NO_RULE_AT_ALL_FIELD_NAME = "noRuleAtAll"; @ArchTest public static Object noRuleAtAll = new Object(); } @ArchIgnore @AnalyzeClasses(packages = "some.pkg") public static class IgnoredArchTest { static final String RULE_ONE_IN_IGNORED_TEST = "someRuleOne"; static final String RULE_TWO_IN_IGNORED_TEST = "someRuleTwo"; @ArchTest public static final ArchRule someRuleOne = all(classes()).should(NEVER_BE_SATISFIED); @ArchTest public static final ArchRule someRuleTwo = all(classes()).should(NEVER_BE_SATISFIED); } }