Xunit Assert.NotNull与C#可空类型兼容问题及强制获取可空版本方案咨询
我来帮你理清这个问题的来龙去脉,以及给出具体的解决办法:
问题根源
你碰到的CS8602(解引用可能为null的引用)警告,确实和Assert.NotNull的实现有关——当项目没启用XUNIT_NULLABLE条件编译符号时,Xunit会使用不带[NotNull]特性的重载版本,这个版本没办法告诉编译器“断言后res一定不为null”,所以后续访问res.Foo时会触发警告。
关于NuGet包的疑问
先给你吃个定心丸:你从NuGet下载的xunit.assert 2.4.1包同时包含可空和非可空两种实现,不是包本身的问题。Xunit源码里通过XUNIT_NULLABLE编译符号来切换实现逻辑,包会根据项目环境自动适配,但有时候需要我们手动触发这个符号的启用。
强制启用带可空注解的Assert版本的方法
按照下面的步骤操作,就能让项目使用带[NotNull]特性的Assert.NotNull重载:
1. 给测试项目添加编译符号
打开你的测试项目的.csproj文件,在<PropertyGroup>节点中添加以下配置:
<DefineConstants>$(DefineConstants);XUNIT_NULLABLE</DefineConstants>
这行代码会在项目已有的编译常量基础上,追加XUNIT_NULLABLE,触发Xunit启用带可空注解的方法实现。
2. 确保项目开启可空上下文
还要确认你的测试项目已经启用了可空引用类型检查——如果没开的话,即使加了编译符号也没用。在.csproj的<PropertyGroup>里检查是否有这行配置:
<Nullable>enable</Nullable>
如果没有,直接加上即可。
3. 验证修改效果
保存项目文件后重新编译,再按住Ctrl点击Assert.NotNull导航到定义,就能看到预期的带注解版本了:
public static void NotNull([NotNull] object? @object)
这时再执行Assert.NotNull(res); Assert.Equal(1, res.Foo);,编译器就会识别到res已经被断言为非null,CS8602警告自然就消失了。
内容的提问来源于stack exchange,提问作者Roman

