使用 Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier 测试 Roslyn 分析器时如何加载程序集?

Pav*_*nin 5 .net c# unit-testing roslyn-code-analysis

验证者有一个方法:

public static Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected)
Run Code Online (Sandbox Code Playgroud)

是否可以加载代码所需类型的程序集source

Dbl*_*Dbl 2

以下代码使其对我有用:

@测试类的使用:

using BindHandlerAnalyzerVerifier = ExtendedAnalyzerVerifier<AnalyzerNamespace>;
Run Code Online (Sandbox Code Playgroud)

测试中:

var diagnostic = BindHandlerAnalyzerVerifier.Diagnostic().WithSpan(4, 1, 12, 2).WithArguments("TestCommand");
await BindHandlerAnalyzerVerifier.VerifyAnalyzerAsync(input, Configure, diagnostic);
Run Code Online (Sandbox Code Playgroud)

装配配置:

private void Configure(CSharpAnalyzerTest<CommandCallsBindHandlerAnalyzer, XUnitVerifier> configuration)
{
    var root = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var enumerateFiles = Directory.EnumerateFiles(root, "*.dll", SearchOption.TopDirectoryOnly).ToArray();
    configuration.ReferenceAssemblies = ReferenceAssemblies.Net.Net50;
    configuration.TestState.AdditionalReferences.AddRange(
        new[]
        {
            MetadataReference.CreateFromFile(typeof(Command).GetTypeInfo().Assembly.Location)
        });
}
Run Code Online (Sandbox Code Playgroud)

工装类:

public class ExtendedAnalyzerVerifier<TAnalyzer> : ExtendedAnalyzerVerifier<TAnalyzer, CSharpAnalyzerTest<TAnalyzer, XUnitVerifier>, XUnitVerifier>
    where TAnalyzer : DiagnosticAnalyzer, new(){}

public class ExtendedAnalyzerVerifier<TAnalyzer, TTest, TVerifier>
    where TAnalyzer : DiagnosticAnalyzer, new()
    where TTest : AnalyzerTest<TVerifier>, new()
    where TVerifier : IVerifier, new()
{
    public static DiagnosticResult Diagnostic()
    {
        var analyzer = new TAnalyzer();
        try
        {
            return Diagnostic(analyzer.SupportedDiagnostics.Single());
        }
        catch (InvalidOperationException ex)
        {
            throw new InvalidOperationException(
                $"'{nameof(Diagnostic)}()' can only be used when the analyzer has a single supported diagnostic. Use the '{nameof(Diagnostic)}(DiagnosticDescriptor)' overload to specify the descriptor from which to create the expected result.",
                ex);
        }
    }
    
    public static DiagnosticResult Diagnostic(string diagnosticId)
    {
        var analyzer = new TAnalyzer();
        try
        {
            return Diagnostic(analyzer.SupportedDiagnostics.Single(i => i.Id == diagnosticId));
        }
        catch (InvalidOperationException ex)
        {
            throw new InvalidOperationException(
                $"'{nameof(Diagnostic)}(string)' can only be used when the analyzer has a single supported diagnostic with the specified ID. Use the '{nameof(Diagnostic)}(DiagnosticDescriptor)' overload to specify the descriptor from which to create the expected result.",
                ex);
        }
    }
    
    public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) => new DiagnosticResult(descriptor);

    public static Task VerifyAnalyzerAsync(string source, Action<TTest>? configure = default, params DiagnosticResult[] expected)
    {
        var test = new TTest
        {
            TestCode = source,
        };

        test.ExpectedDiagnostics.AddRange(expected);
        configure?.Invoke(test);
        
        return test.RunAsync(CancellationToken.None);
    }
}
Run Code Online (Sandbox Code Playgroud)