如何使用 ArchUnit 在测试 class 中忽略 classes

How to ignore classes in test class with ArchUnit

我写了我的第一个 ArchUnit 测试:

import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.*;
// more non-static imports

@RunWith(ArchUnitRunner.class)
@AnalyzeClasses(packages = "my.domain.project")
public class PackageStructureTests {

    @ArchTest public static final ArchRule NO_CYCLES = slices().matching("my.domain.project.(**)")
            .namingSlices("package:").should().beFreeOfCycles();

}

问题是它还在测试中分析 类,但不遵循简单的依赖约束。

如何将测试限制在 "production" 类?

该项目是使用 Maven 构建的,因此 类 位于单独的目录中。

将 类 与以 "Tests" 或其他名称结尾的名称分开是不够的,因为有许多 类 不是测试,但仅存在于测试类路径中.

似乎 API 在这方面的指导不是很好,因为您不是第一个对此感到疑惑的人(这也是 Github 上的第 1 期 https://github.com/TNG/ArchUnit/issues/1).

为了回答这个问题,注释 @AnalyseClasses 有一个额外的属性 importOptions,它采用 ImportOption 的任意实现。您可以在此处指定要包含的 Location(基本上是 URI)。

由于排除测试很常见,这个 ImportOption 已经预定义(对于 Maven 和 Gradle < 4.0),所以你可以写

@AnalyzeClasses(..., importOptions = ImportOption.DoNotIncludeTests.class)
public class MyTest{ ... }

我认为没有适用于所有设置的通用解决方案(因此您可以自由地编写自己的 ImportOption 来决定要包含哪些位置)。但是,对于标准 Maven 和 Gradle 设置,它应该可以工作。

如果您不使用 archunit-junit(在撰写本文时支持 ArchUnit JUnit 4),而是使用“原生”ArchUnit,请使用(例如)

com.tngtech.archunit.core.domain.JavaClasses classes 
  = new com.tngtech.archunit.core.importer.ClassFileImporter()
    .withImportOption(
      new com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests())
    .importPackages("my.random.package");