使用NUnit断言Type集合时,Has.All.Property(nameof(Type.Namespace))为何失败?
NUnit集合断言中Type.Namespace属性找不到的问题解决
我想用NUnit断言所有目标Type都属于预期命名空间,写了下面的代码:
IReadOnlyCollection<Type> types = GetInterestingTypes(); // 其他地方定义的方法 Assert.That(types, Has.All.Property(nameof(Type.Namespace)).StartsWith("MyNamespace"));
这段代码抛出ArgumentException:Property Namespace not found on ...,但单独对每个Type执行断言Has.Property(nameof(Type.Namespace)).StartsWith("MyNamespace")却能正常通过。
最小复现代码
using System; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using NUnit.Framework; namespace MyNamespace { internal class MyTests { [Test] public void TestsWithinNamespace() { var types = new[] {typeof(Foo), typeof(NestedNamespace.Bar)}; foreach (var type in types) { // 执行通过 Assert.That(type, Has.Property(nameof(Type.Namespace)).StartsWith("MyNamespace")); } // 执行失败 Assert.That(types, Has.All.Property(nameof(Type.Namespace)).StartsWith("MyNamespace")); } } public class Foo { } namespace NestedNamespace { public class Bar { } } }
错误信息
System.ArgumentException : Property Namespace was not found on MyNamespace.Foo. Parameter name: name at NUnit.Framework.Constraints.PropertyConstraint.ApplyTo[TActual](TActual actual) at NUnit.Framework.Constraints.AllItemsConstraint.ApplyTo[TActual](TActual actual) at NUnit.Framework.Assert.That[TActual](TActual actual, IResolveConstraint expression, String message, Object[] args) at MyNamespace.MyTests.TestsWithinNamespace()
问题原因
NUnit的Has.All.Property约束处理Type对象时,会尝试通过实例属性查找Namespace,但Type.Namespace本质是依赖反射的属性(属于TypeInfo范畴),集合断言的属性查找逻辑和单个对象断言的逻辑存在差异,导致无法识别该属性。
解决方法
有两种可靠的修复方式:
方式1:使用Has.All.Matches自定义匹配逻辑
手动在匹配器中获取Namespace属性,绕开NUnit的属性查找逻辑:
Assert.That(types, Has.All.Matches<Type>(t => t.Namespace.StartsWith("MyNamespace")));
方式2:投影后断言
先将集合中的Type转换为对应的命名空间字符串,再断言所有字符串符合要求:
Assert.That(types.Select(t => t.Namespace), Has.All.StartsWith("MyNamespace"));
这两种方式都能正确验证所有Type的命名空间是否符合预期,规避了NUnit集合属性断言的逻辑问题。
内容的提问来源于stack exchange,提问作者Andrew McClement
相关产品推荐
相关产品推荐

