问题
如何为包含大量自定义界面引用的集合正确使用带有NUnit3集合约束的自定义IComparer<T>
?
我尝试了什么
我有一个返回IEnumerable<IInterface>
实例的类,其中IInterface
的定义如下:
public interface IInterface
{
string PropertyOne { get; }
string PropertyTwo { get; }
}
我正在尝试使用NUnit3中的集合约束和自定义IComparer<T>
,但它无效。要创建要测试的模拟对象,
我正在使用Moq。测试看起来大致如下:
[Test]
public void MyTest()
{
var mockObject = new Mock<IInterface>();
mockObject.Setup(x => x.PropertyOne).Returns("Foo");
mockObject.Setup(x => x.PropertyTwo).Returns("Bar");
var collection = myObject.Collection;
Assert.That(collection, Contains.Item(mockObject).Using(this));
}
测试用例包含在继承自以下基类
的类中public class TestBase : IComparer<IInterface>
{
public int Compare(IInterface one, IInterface two) { /* some code */ }
}
当我在上面的Compare
方法上设置断点时,我发现NUnit完全忽略了我的比较器,选择在底层对象上使用ToString()
实现,尽管事实如此它没有被界面暴露。
答案 0 :(得分:0)
此处的问题是Nunit3
与IComparer<T>
一起使用自定义Constraints
的方式。如果提供了自定义比较器Nunit3
,则将其存储在所谓的外部比较器列表中。每个IComparer<T>
都将在内部存储为EqualityAdapter
。稍后在比较点时,它会尝试将objects
强制转换为T
,以便决定是否应该使用自定义比较器。
我们在您的示例中,您有一个ICollection<IInterface>
,但您创建的Constraint
使用了Mock<IInterface>
。显然IInterface
无法与Mock<IInterface>
进行比较。
我个人发现这种误导,因为问题将在运行时弹出,而不是在编译时。以下示例将解释该问题:
错误的使用示例
//notice that Constraints is created for the int but IComparer<string> is used
List<string> strs = new List<string> {"1", "2", "3"};
Assert.That(strs, Contains.Item(5).Using((IComparer<string>) comparer));
正确的用法示例
//notice that Constraints is created for the string and IComparer<string> is used
List<string> strs = new List<string> {"1", "2", "3"};
Assert.That(strs, Contains.Item("5").Using((IComparer<string>) comparer));