package com.tngtech.archunit.junit; import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaClasses; import com.tngtech.archunit.core.importer.ImportOption; import com.tngtech.archunit.core.importer.ImportOptions; import com.tngtech.archunit.core.importer.Location; import com.tngtech.archunit.junit.ClassCache.CacheClassFileImporter; import com.tngtech.archunit.testutil.ArchConfigurationRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.InjectMocks; import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyCollection; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @SuppressWarnings("unchecked") public class ClassCacheTest { @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule(); @Rule public final ExpectedException thrown = ExpectedException.none(); @Rule public final ArchConfigurationRule archConfigurationRule = new ArchConfigurationRule() .resolveAdditionalDependenciesFromClassPath(false); @Spy private CacheClassFileImporter cacheClassFileImporter; @InjectMocks private ClassCache cache = new ClassCache(); @Test public void loads_classes() { JavaClasses classes = cache.getClassesToAnalyzeFor(TestClass.class); assertThat(classes).as("Classes were found").isNotEmpty(); } @Test @SuppressWarnings("unchecked") public void reuses_loaded_classes_by_test() { cache.getClassesToAnalyzeFor(TestClass.class); cache.getClassesToAnalyzeFor(TestClass.class); verifyNumberOfImports(1); } @Test @SuppressWarnings("unchecked") public void reuses_loaded_classes_by_urls() { cache.getClassesToAnalyzeFor(TestClass.class); cache.getClassesToAnalyzeFor(EquivalentTestClass.class); verifyNumberOfImports(1); } @Test public void rejects_missing_analyze_annotation() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage(Object.class.getSimpleName()); thrown.expectMessage("must be annotated"); thrown.expectMessage(AnalyzeClasses.class.getSimpleName()); cache.getClassesToAnalyzeFor(Object.class); } @Test public void filters_jars_relative_to_class() { JavaClasses classes = cache.getClassesToAnalyzeFor(TestClassWithFilterJustByPackageOfClass.class); assertThat(classes).isNotEmpty(); for (JavaClass clazz : classes) { assertThat(clazz.getPackage()).doesNotContain("tngtech"); } } @Test public void gets_all_classes_relative_to_class() { JavaClasses classes = cache.getClassesToAnalyzeFor(TestClassWithFilterJustByPackageOfClass.class); assertThat(classes).isNotEmpty(); } @Test public void filters_urls() { JavaClasses classes = cache.getClassesToAnalyzeFor(TestClassFilteringJustJUnitJars.class); assertThat(classes).isNotEmpty(); for (JavaClass clazz : classes) { assertThat(clazz.getPackage()).doesNotContain(ClassCache.class.getSimpleName()); assertThat(clazz.getPackage()).contains("junit"); } } @Test public void non_existing_packages_are_ignored() { JavaClasses first = cache.getClassesToAnalyzeFor(TestClassWithNonExistingPackage.class); JavaClasses second = cache.getClassesToAnalyzeFor(TestClassWithFilterJustByPackageOfClass.class); assertThat(first).isEqualTo(second); verifyNumberOfImports(1); } @Test public void distinguishes_import_option_when_caching() { JavaClasses importingWholeClasspathWithFilter = cache.getClassesToAnalyzeFor(TestClassFilteringJustJUnitJars.class); JavaClasses importingWholeClasspathWithEquivalentButDifferentFilter = cache.getClassesToAnalyzeFor(TestClassFilteringJustJUnitJarsWithDifferentFilter.class); assertThat(importingWholeClasspathWithFilter) .as("number of classes imported") .hasSameSizeAs(importingWholeClasspathWithEquivalentButDifferentFilter); verifyNumberOfImports(2); } private void verifyNumberOfImports(int number) { verify(cacheClassFileImporter, times(number)).importClasses(any(ImportOptions.class), anyCollection()); verifyNoMoreInteractions(cacheClassFileImporter); } @AnalyzeClasses(packages = "com.tngtech.archunit.junit") public static class TestClass { } @AnalyzeClasses(packages = "com.tngtech.archunit.junit") public static class EquivalentTestClass { } @AnalyzeClasses(packagesOf = Rule.class) public static class TestClassWithFilterJustByPackageOfClass { } @AnalyzeClasses(packages = "something.that.doesnt.exist", packagesOf = Rule.class) public static class TestClassWithNonExistingPackage { } @AnalyzeClasses(importOptions = TestFilterForJUnitJars.class) public static class TestClassFilteringJustJUnitJars { } @AnalyzeClasses(importOptions = AnotherTestFilterForJUnitJars.class) public static class TestClassFilteringJustJUnitJarsWithDifferentFilter { } public static class TestFilterForJUnitJars implements ImportOption { @Override public boolean includes(Location location) { return location.contains("junit") && location.contains(".jar"); } } public static class AnotherTestFilterForJUnitJars implements ImportOption { private TestFilterForJUnitJars filter = new TestFilterForJUnitJars(); @Override public boolean includes(Location location) { return filter.includes(location); } } }