问题描述
#UPD:这完全是我的错误。我在回答中发布的一些细节
为什么 Roslyn 代码修复测试不仅为 test-source-code-sample 调用 VerifyDiagnostics
,而且还为 fixed-code-sample 调用?
Visual Studio 模板项目“Analyzer with Code Fix”的单元测试依赖于这样的方法:
public static async Task VerifyCodeFixAsync(
/*1*/ string source,/*2*/ DiagnosticResult[] expected,/*3*/ string fixedSource)
{
var test = new Test
{
TestCode = source,FixedCode = fixedSource,};
test.ExpectedDiagnostics.AddRange(expected);
await test.RunAsync(CancellationToken.None);
}
我是这样理解争论的:
/*1*/
- 测试代码示例,有故意问题的测试分析器可以找到它们
/*2*/
- 预期 - 关于这些故意问题的特殊数据(包括每个问题的位置)
/*3*/
- 固定代码示例 - 分析器发现,这是测试代码示例在某些地方应用自动代码修复后应该变成的样子
所以,我希望 test.RunAsync
(在最后一行调用)应该在类似于以下场景的幕后工作:
- 第一次将分析器发现的问题与
expecteds
进行比较 - 它们应该相等 - 第二次将自动代码修复应用于测试代码示例
- 最后比较上一个生成的代码。步骤,提供
fixedSource
(/*3*/
)
这就是我所期望的。
但是!如果您查看类 Microsoft.CodeAnalysis.Testing.CodeFixTest<>
的源代码,您会发现 RunAsync
方法的这种实现:
public override async Task RunAsync(CancellationToken cancellationToken = default)
{
...
await VerifyDiagnosticsAsync(new EvaluatedProjectState(testState,...); // <--- Line A
if (CodeFixExpected())
{
await VerifyDiagnosticsAsync(new EvaluatedProjectState(fixedState,...); // <--- Line B
...
}
}
如果我的分析仪:
- 如果我通过了not-empty
expected
,则在行 B 处测试失败并显示消息:
Assert.AreEqual 失败。预期:1>。实际:0>。语境: 固定状态
的诊断'因为它看起来像是为什么将固定代码示例中发现的问题与 expected
进行比较(我认为这是一个错误,因为固定代码不应该包含问题(根据定义))
#UPD: Roslyn 代码是正确的。这是我的错误 - 请参阅我发布的答案。
- 如果我通过 empty
expected
,B 行应该得到满足,但在 A 行测试失败(这次很正常)并显示消息:立>
Assert.AreEqual 失败。预期:0>。实际:1>。语境: 测试状态
的诊断所以我的问题是:为什么 Roslyn 代码修复测试将 expected
与两者进行比较(第一个测试代码示例,对我来说完全符合预期),然后与固定代码示例进行比较,这使得测试永远不可能成功了吗?
也许我遗漏了什么......
如果有任何想法,我将不胜感激
解决方法
我想通了。
这都怪我。我错误地将 CSharpCodeFixVerifier
与另一个 AnalyzerCodeFixProvider
参数化(不是我应该在那里使用的那个)。
因此,第二次调用 VerifyDiagnostics
(使用固定代码样本作为 state
参数)是正确的。而且,我想,它会检查固定代码样本是否没有诊断出的问题。