package com.tngtech.archunit.junit; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.junit.ArchUnitRunner.SharedCache; import org.junit.Before; import org.junit.Rule; import org.junit.Test; 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.ArchUnitRunnerRunsMethodsTest.ArchTestWithIgnoredMethod.toBeIgnored; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsMethodsTest.ArchTestWithIllegalTestMethods.noParams; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsMethodsTest.ArchTestWithIllegalTestMethods.tooManyParams; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsMethodsTest.ArchTestWithTestMethod.testSomething; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsMethodsTest.IgnoredArchTest.toBeIgnoredOne; import static com.tngtech.archunit.junit.ArchUnitRunnerRunsMethodsTest.IgnoredArchTest.toBeIgnoredTwo; import static com.tngtech.archunit.junit.ArchUnitRunnerTestUtils.getRule; import static com.tngtech.archunit.junit.ArchUnitRunnerTestUtils.newRunnerFor; 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 ArchUnitRunnerRunsMethodsTest { @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 = newRunnerFor(ArchTestWithTestMethod.class); private JavaClasses cachedClasses = javaClassesViaReflection(ArchUnitRunnerRunsMethodsTest.class); @Before public void setUp() { when(cache.get()).thenReturn(classCache); when(classCache.getClassesToAnalyzeFor(any(Class.class))).thenReturn(cachedClasses); } @Test public void executes_test_methods_and_supplies_JavaClasses() throws InitializationError { runner.runChild(getRule(testSomething, runner), runNotifier); verify(runNotifier, never()).fireTestFailure(any(Failure.class)); verify(runNotifier).fireTestFinished(descriptionCaptor.capture()); assertThat(descriptionCaptor.getAllValues()).extractingResultOf("getMethodName") .contains(testSomething); assertThat(ArchTestWithTestMethod.suppliedClasses).as("Supplied Classes").isEqualTo(cachedClasses); } @Test public void fails_methods_with_no_parameters() throws InitializationError { runAndAssertWrongParametersForChild(noParams, new ArchUnitRunner(ArchTestWithIllegalTestMethods.class)); } @Test public void fails_methods_with_too_many_parameters() throws InitializationError { runAndAssertWrongParametersForChild(tooManyParams, new ArchUnitRunner(ArchTestWithIllegalTestMethods.class)); } private void runAndAssertWrongParametersForChild(String name, ArchUnitRunner runner) { runner.runChild(getRule(name, runner), runNotifier); verify(runNotifier).fireTestFailure(failureCaptor.capture()); Failure failure = failureCaptor.getValue(); assertThat(failure.getDescription().toString()).as("Failure description").contains(name); assertThat(failure.getException().getMessage()).as("Failure Cause") .contains("@" + ArchTest.class.getSimpleName()) .contains("exactly one parameter of type " + JavaClasses.class.getSimpleName()); } @Test public void ignores_all_methods_in_classes_annotated_with_ArchIgnore() throws InitializationError { ArchUnitRunner runner = new ArchUnitRunner(IgnoredArchTest.class); runner.runChild(getRule(toBeIgnoredOne, runner), runNotifier); runner.runChild(getRule(toBeIgnoredTwo, runner), runNotifier); verify(runNotifier, times(2)).fireTestIgnored(descriptionCaptor.capture()); assertThat(descriptionCaptor.getAllValues()).extractingResultOf("getMethodName") .contains(toBeIgnoredOne) .contains(toBeIgnoredTwo); } @Test public void ignores_methods_annotated_with_ArchIgnore() throws InitializationError { ArchUnitRunner runner = new ArchUnitRunner(ArchTestWithIgnoredMethod.class); runner.runChild(getRule(toBeIgnored, runner), runNotifier); verify(runNotifier).fireTestIgnored(descriptionCaptor.capture()); assertThat(descriptionCaptor.getValue().toString()).contains(toBeIgnored); } @AnalyzeClasses(packages = "some.pkg") public static class ArchTestWithTestMethod { static final String testSomething = "testSomething"; static JavaClasses suppliedClasses; @ArchTest public static void testSomething(JavaClasses classes) { suppliedClasses = classes; } } @AnalyzeClasses(packages = "some.pkg") public static class ArchTestWithIllegalTestMethods { static final String noParams = "noParams"; static final String tooManyParams = "tooManyParams"; @ArchTest public static void noParams() { } @ArchTest public static void tooManyParams(JavaClasses classes, int tooMuch) { } } @ArchIgnore @AnalyzeClasses(packages = "some.pkg") public static class IgnoredArchTest { static final String toBeIgnoredOne = "toBeIgnoredOne"; static final String toBeIgnoredTwo = "toBeIgnoredTwo"; @ArchTest public static void toBeIgnoredOne(JavaClasses classes) { } @ArchTest public static void toBeIgnoredTwo(JavaClasses classes) { } } @AnalyzeClasses(packages = "some.pkg") public static class ArchTestWithIgnoredMethod { static final String toBeIgnored = "toBeIgnored"; @ArchIgnore @ArchTest public static void toBeIgnored(JavaClasses classes) { } } }