如何在单元测试中结合使用Roslyn语法分析器与源代码生成器
同时测试依赖源代码生成器的语法分析器
核心思路
要在单次测试里同时跑源代码生成器和语法分析器,关键是让测试流程先触发源代码生成,再用生成的特性驱动语法分析器测试,把两个环节串成连贯的流水线。
具体实现方案
1. 利用测试框架初始化钩子提前执行代码生成
在xUnit、NUnit这类常用测试框架中,借助全局初始化特性,在所有测试用例运行前完成代码生成:
- 调用你的源代码生成器,传入预先准备的测试用原始代码
- 将生成的带特性的代码输出到测试项目的临时目录,或直接存入内存
- 确保语法分析器能正确加载到这些生成的特性代码
2. 内存中构建编译上下文(推荐)
跳过磁盘IO开销,直接在内存里搭建完整编译环境:
- 创建
CSharpCompilation实例,添加原始测试代码和源代码生成器的输出代码 - 让语法分析器直接基于这个内存编译上下文工作,生成的特性会被实时识别
示例伪代码:
// 初始化:运行源代码生成器 var generator = new YourSourceGenerator(); var inputTree = CSharpSyntaxTree.ParseText("待测试的原始代码"); var baseCompilation = CSharpCompilation.Create("TestCompilation") .AddSyntaxTrees(inputTree) .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)); // 执行生成并更新编译上下文 var driver = CSharpGeneratorDriver.Create(generator); driver.RunGeneratorsAndUpdateCompilation(baseCompilation, out var updatedCompilation, out _); // 测试语法分析器 var analyzer = new YourSyntaxAnalyzer(); var diagnostics = analyzer.Analyze(updatedCompilation); // 断言诊断结果符合预期
3. 调整测试项目的MSBuild配置
如果是基于MSBuild的测试项目,可通过项目文件配置实现:
- 将源代码生成器项目设为测试项目的依赖项
- 启用
EmitCompilerGeneratedFiles属性,让生成的代码输出到可访问目录 - 在测试代码中直接引用该目录下的生成文件,再初始化语法分析器
注意事项
- 必须保证特性代码在语法分析器运行前完全生成并可访问,避免“找不到特性”的错误
- 测试用例要覆盖特性生成异常的场景,比如生成器输出无效代码时,语法分析器的表现是否符合预期
- 内存编译时要注意程序集引用的完整性,确保所有必要依赖都被添加到编译上下文
内容的提问来源于stack exchange,提问作者crashtua
相关产品推荐
相关产品推荐

