Theory必须搭配InlineData等数据源使用,否则运行时直接跳过;参数类型数量须严格匹配,值须为编译期常量,null仅支持可空类型,字符串不可含未转义特殊字符,多条InlineData生成独立测试用例。

Theory 必须搭配数据源使用,单独标记 Theory 会导致测试发现失败 —— 这不是警告,是运行时直接跳过该方法。
Theory 方法必须有匹配的参数签名才能接收 InlineData
Theory 方法本身不执行,它只是个“占位符”,真正触发执行的是每一条 InlineData 提供的参数组合。如果参数类型或数量对不上,编译能过,但测试运行器在发现阶段就会静默忽略该用例,甚至不报错。
-
InlineData里的值顺序必须严格对应方法参数声明顺序 - 每个值的运行时类型必须能隐式转换为目标参数类型(比如
InlineData(1, "hello", true)对应int a, string b, bool c) - 不支持
null传给非可空引用类型(如string可以,int不行;要传int?才能写InlineData(null)) - 字符串字面量中不能直接写换行或未转义双引号,否则编译报错:C# 层面就过不去
示例错误写法:
[Theory]
[InlineData(1, null, "ok")] // ❌ int? 才能接 null,这里第二个参数是 int
public void Process(int id, int status, string msg) { ... }
InlineData 的实际限制比看起来更硬
它看着灵活,其实是个“编译期常量列表”:所有值必须是编译期确定的常量(const 表达式),不能是变量、方法调用、new 实例,也不能是 default 或 typeof(...)。
- 支持:
42、"abc"、true、(int)Enum.Value、1L - 不支持:
DateTime.Now、Guid.NewGuid()、new int[]{1,2}、MyHelper.GetTestValue() - 特别注意:枚举成员名本身不是常量,得显式转成基础类型,比如
InlineData((int)HttpStatusCode.OK)
如果你需要动态数据、对象实例或复杂结构,InlineData 就到头了,得切到 MemberData 或自定义 TheoryData。
多个 InlineData 是并行注册,不是叠加传参
每个 InlineData 属性生成一条独立测试用例,不是把多条合起来喂给一次调用。这点容易误解,尤其当看到测试结果里显示 “Add_ShouldReturnCorrectSum(2, 3, 5)” 和 “Add_ShouldReturnCorrectSum(-1, 1, 0)” 分开列出来时。
- 测试报告里每条都是独立生命周期:Setup → 执行 → Teardown(xUnit 默认每个测试方法新建实例,除非你手动复用)
- 断言失败只影响当前这组数据,其他组照常跑、照常报结果
- 但整个
Theory方法的“总体状态”取决于全部用例是否通过:只要有一条挂了,VS 测试窗口里这个方法名就标红
这也意味着:别指望在 Theory 方法里靠共享字段缓存状态 —— 每次调用都是干净实例,字段重置为默认值。
真正麻烦的点不在语法,而在于调试和可维护性。当你堆了 20 条 InlineData,其中第 17 条失败,错误堆栈只告诉你方法名和参数值,不会自动高亮哪一行 InlineData 对应它 —— 你得自己数,或者加注释对齐。更隐蔽的是类型隐式转换失败时,它不报 InvalidCastException,而是直接“找不到匹配测试用例”,连日志都安静。



















