我正在使用 xUnit 2.6.3(最新稳定版本)来测试 .Net 8 项目。我有一个继承自抽象类的对象,并且我正在测试的方法具有基类的返回类型。基类有一个名为 Data 的 WidgetData 类型抽象属性,该属性仅具有 getter,派生类通过返回 QueryCountWidgetData 类型(继承自 WidgetData)的对象来重写该属性。没有二传手。
我可以单步调试并验证返回的对象是否与我预期的测试对象匹配,但是当我调用 Assert.Equivalent(expected, result, true) 时,xUnit 会抛出 System.ArgumentException 并显示以下消息:具有相同键的项目有已经添加了。关键:数据。它是从 AssertHelper.GetGettersForType(Type type) 方法抛出的。我的对象定义和测试代码如下。我是否做错了什么,xUnit 是否还不能容纳协变返回类型,或者这是完全不同的东西?
小部件类
public abstract class Widget
{
public virtual string Title { get; set; }
public int RowSpan { get; set; }
public int ColumnSpan { get; set; }
public int Row { get; set; }
public int Column { get; set; }
public string BackgroundColor { get; set; } = "DarkGray";
public int DefaultFontSize { get; set; }
public abstract WidgetData Data { get; }
public abstract void SetData(object data);
}
QueryWidget 类
public abstract class QueryWidget : Widget
{
public Guid QueryId { get; set; }
public List<SelectableQueryParameter> Parameters { get; set; }
public DateSearchContext SearchContext { get; set; }
}
QueryCountWidget 类
public class QueryCountWidget : QueryWidget
{
private QueryCountWidgetData _data;
public override QueryCountWidgetData Data => _data;
public override void SetData(object data)
{
if (data is QueryCountWidgetData widgetData)
{
_data = widgetData;
}
}
}
WidgetData 和 QueryCountWidgetData 类
public abstract class WidgetData
{ }
public class QueryCountWidgetData : WidgetData
{
public int? Count { get; set; }
}
测试方法(_queryCountWidgetNode 填充在测试装置中;异常在最后的 Assert.Equivalent 调用处失败)
[Fact]
public void DeserializeQueryCountWidget()
{
var result = DashboardXmlDeserializer.GetWidgetFromXmlNode(_queryCountWidgetNode);
Assert.NotNull(result);
Assert.IsType<QueryCountWidget>(result);
var expected = new QueryCountWidget
{
Title = "QueryCount with Param",
BackgroundColor = "DarkGray",
Row = 0,
RowSpan = 1,
Column = 8,
ColumnSpan = 1,
SearchContext = new DateSearchContext
{
Name = "",
DateFieldId = "",
DateSearchShortcut = "All"
},
Parameters = new List<SelectableQueryParameter>
{
new SelectableQueryParameter
{
Name = "@TestParam",
Value = "Scrap",
DataTypeString = "System.String",
Hidden = false,
}
},
QueryId = Guid.Parse("f545ad33-647c-4596-ad7d-0b0a113e7e98"),
};
Assert.Equivalent(expected, result, true);
}
我开始使用旧版本的 xUnit,但我已将 xunit 更新到 2.6.3,将 xunit.runner.visualstudio 更新到 2.5.5;两者都是最新的稳定版本。我已经验证我可以对每个属性单独调用 Assert.Equivalent ,不会出现问题。我还更改了 Widget 类来测试:
不幸的是,仅有的两个似乎有效的更改阻止了我按照我想要的方式使用这些类。我有十几种其他类型的小部件,每种都有自己关联的 WidgetData 派生类型。我真的不想单独测试每个属性,因为如果将新属性添加到 Widget 类中,这并不能说明未来的开发。有没有办法让它与 xUnit 一起工作而不破坏我的类结构?
您对
xUnit中的
Assert.Equivalent
的问题似乎源于 xUnit 的断言机制处理继承类中的属性的方式发生冲突,特别是在处理重写的属性时。
在 xUnit 中,
Assert.Equivalent
旨在比较两个对象的结构相等性,这意味着它检查它们是否具有相同的数据,而不一定是相同的实例。但是,当它遇到重写的属性时,尤其是在像您这样具有协变返回类型的场景中,它可能无法正确处理比较,从而导致像您遇到的那样的异常。
我建议你使用流行的NuGet包
FluentAssertions
并替换这行代码:
Assert.Equivalent(expected, result, true);
与:
result.Should().BeEquivalentTo(expected);
这按预期工作,不会引发任何错误,并且在我看来更具可读性。