You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用ArchUnitNET与NetArchTest检测.NET解决方案中仅用于单元测试的代码

如何用ArchUnitNET和NetArchTest找出仅被单元测试调用的.NET代码

咱们先理清楚核心需求:你要找出MyTypes命名空间下(排除所有带Test的命名空间),那些仅被测试代码调用、完全没有被业务代码使用的类型或方法。你的现有思路只检查了测试代码是否调用这些方法,或者方法是否被自身命名空间调用,但没抓住“仅被测试调用”的核心——也就是这些代码没有被非测试的业务逻辑引用。

下面分别给你两个工具的正确实现方案:


一、ArchUnitNET 实现方案

ArchUnitNET的核心是定义清晰的类型/方法集合,然后验证业务方法必须被至少一个非测试的业务类型调用——反过来,没被业务类型调用的方法,就是仅被测试调用(或完全未被调用)的目标代码。

// 1. 定义基础类型集合
var businessTypes = Types()
    .That().ResideInNamespace("^MyTypes.*", true)
    .And().DoNotResideInNamespace(".*(?i)Test.*", true)
    .As("非测试业务类型");

var testTypes = Types()
    .That().ResideInNamespace(".*(?i)Test.*", true)
    .As("测试类型");

var businessMethods = MethodMembers()
    .That().AreDeclaredIn(businessTypes)
    .And().AreNoConstructors()
    .And().AreNotPrivate() // 只检查公开/内部方法,私有方法通常不会被外部调用
    .As("业务类型的公开/内部方法");

// 2. 核心规则:业务方法必须被至少一个业务类型调用(排除测试调用)
businessMethods
    .Should().BeCalledByAny(businessTypes)
    .Because("业务方法应该被非测试代码使用;如果没有,说明它仅用于测试")
    .Check(architecture);

说明

  • 当检查失败时,ArchUnitNET会直接列出所有没有被业务代码调用的方法,这些就是你要找的“仅用于测试”的代码。
  • 如果需要检查整个类型是否仅被测试调用,可以把规则改成验证类型被业务类型引用,而不是方法。

二、NetArchTest 实现方案

NetArchTest需要通过自定义规则来检查方法的调用来源,核心是验证每个业务方法是否存在至少一个来自非Test命名空间的业务调用者。

[Test]
public void BusinessMethods_Should_BeUsedByNonTestCode()
{
    var businessTypes = Types.InCurrentDomain()
        .That().ResideInNamespaceMatching("^MyTypes.*")
        .And().DoNotResideInNamespaceMatching(".*(?i)Test.*");

    var result = businessTypes.Should().MeetCustomRule(new IsUsedByNonTestCode()).GetResult();

    Assert.IsTrue(result.IsSuccessful, 
        $"以下类型/方法仅被测试代码调用:\n{string.Join("\n", result.FailingTypeNames)}");
}

private class IsUsedByNonTestCode : ICustomRule
{
    private readonly Regex _businessNamespaceRegex = new Regex("^MyTypes.*", RegexOptions.IgnoreCase);
    private readonly Regex _testNamespaceRegex = new Regex(".*Test.*", RegexOptions.IgnoreCase);

    public bool MeetsRule(TypeDefinition type)
    {
        // 筛选出类型中所有非私有、非构造方法
        var targetMethods = type.Methods
            .Where(m => !m.IsPrivate && !m.IsConstructor);

        // 如果类型没有符合条件的方法,默认通过(可根据需求调整)
        if (!targetMethods.Any())
            return true;

        // 验证每个方法是否至少有一个来自业务命名空间的非测试调用者
        return targetMethods.All(method => 
            method.Usages.Any(usage => 
                !_testNamespaceRegex.IsMatch(usage.DeclaringType.Namespace) 
                && _businessNamespaceRegex.IsMatch(usage.DeclaringType.Namespace)));
    }
}

说明

  • 确保测试运行时加载了所有相关程序集(业务程序集和测试程序集),InCurrentDomain()才能正确扫描到调用关系。
  • 对于标记为internal的方法,如果测试项目通过InternalsVisibleTo授权访问,NetArchTest也能识别到对应的调用关系。

额外注意点

  1. 如果要找完全未被任何代码调用的“死代码”,可以在规则中额外排除这种情况(比如检查方法是否有任何调用者,包括测试)。
  2. 两个工具都需要正确配置程序集扫描范围,ArchUnitNET可以通过Architecture.LoadAssemblies()指定要扫描的程序集,避免扫描无关代码。

内容的提问来源于stack exchange,提问作者Newnamtab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:44:05