使用Roslyn解析布尔表达式遇CS0103错误,求解决集成测试JSON断言问题
解决Roslyn解析断言字符串时的"entry不存在"错误
我完全懂你碰到的问题——你想用Roslyn执行JSON测试用例里的断言表达式,但脚本引擎压根不知道entry是什么,因为你没把这个测试对象注入到脚本的上下文环境里,所以才抛出了CS0103这个错误。咱们一步步来搞定它:
1. 先搞清楚问题根源
结合你提到的JSON结构,你的测试用例大概是这样的:
{ "entries": [ { "name": "商品价格验证", "assertion": "entry.Price > 99", "Price": 129 } ] }
当你直接拿entry.Price > 99这个字符串给Roslyn执行时,脚本环境里没有任何叫entry的变量,自然会报错说“名称不存在”。
2. 核心解决方案:给Roslyn注入entry变量
你需要在执行脚本前,把当前测试用例的entry对象传递到Roslyn的脚本上下文里。下面是具体的C#代码示例:
第一步:先把JSON结构映射成C#实体类
先定义和JSON对应的类,方便后续处理测试数据:
public class TestEntry { public string Name { get; set; } public string Assertion { get; set; } // 根据你的JSON字段添加对应属性,比如价格、ID等 public int Price { get; set; } }
第二步:用Roslyn执行断言并传入entry
通过ScriptOptions配置必要的程序集引用,再用全局上下文把entry对象传给脚本:
using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; using System.Text.Json; // 从JSON文件加载测试用例(这里用示例数据代替文件读取) var jsonContent = @"{""entries"": [{""name"":""商品价格验证"",""assertion"":""entry.Price > 99"",""Price"":129}]}"; var testCase = JsonSerializer.Deserialize<TestCase>(jsonContent); foreach (var entry in testCase.entries) { try { // 配置脚本选项:添加当前程序集引用(因为TestEntry在当前项目里)、导入命名空间 var scriptOptions = ScriptOptions.Default .AddReferences(typeof(TestEntry).Assembly) .AddImports(typeof(TestEntry).Namespace); // 用匿名类型作为全局上下文,把当前entry对象传进去 var globals = new { entry = entry }; // 执行断言脚本,获取布尔结果 bool assertionResult = await CSharpScript.EvaluateAsync<bool>(entry.Assertion, scriptOptions, globals); Console.WriteLine($"测试用例「{entry.Name}」结果:{(assertionResult ? "通过" : "失败")}"); } catch (CompilationErrorException ex) { Console.WriteLine($"测试用例「{entry.Name}」编译错误:\n{string.Join("\n", ex.Diagnostics)}"); } } // 对应JSON的根类 public class TestCase { public List<TestEntry> entries { get; set; } }
3. 几个关键注意事项
- 全局上下文的作用:这里的匿名类型
new { entry = entry }是给Roslyn脚本提供全局变量的容器,脚本里的entry会直接映射到这个容器的entry属性,这样脚本就知道它指代的是哪个测试对象了。 - 程序集和命名空间:必须添加包含
TestEntry的程序集引用和对应命名空间,否则脚本会识别不了TestEntry的类型。 - 异步处理:
EvaluateAsync是异步方法,生产环境里尽量用await,如果是控制台测试可以用.Result但不推荐。
4. 扩展:处理复杂断言场景
如果你的断言需要用到DateTime、LINQ或者其他系统类型,只需要在ScriptOptions里添加对应的引用和命名空间就行:
var scriptOptions = ScriptOptions.Default .AddReferences(typeof(TestEntry).Assembly, typeof(DateTime).Assembly, typeof(Enumerable).Assembly) .AddImports(typeof(TestEntry).Namespace, "System", "System.Linq");
这样就能解决entry不存在的问题,顺利把JSON里的断言字符串解析成布尔结果啦!
内容的提问来源于stack exchange,提问作者Emiliano Montesdeoca
相关产品推荐
相关产品推荐

