此时,我正在使用NUnit进行比较。 (我打算使用不同的单元测试框架进行此测试。)我正在使用ILGenerator动态调用已通过Entity Framework 6.0映射的存储过程。 (存储过程只是从SQL Server 2012数据库中的表值用户定义函数中进行选择。)
代码似乎工作正常,但我无法让Assert通过。这是我的错误:
Expected: equivalent to <
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result> >
But was: <
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result>,
<CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result> >
at NUnit.Framework.Assert.That(Object actual, IResolveConstraint expression, String message, Object[] args)
at NUnit.Framework.CollectionAssert.AreEquivalent(IEnumerable expected, IEnumerable actual, String message, Object[] args)
at NUnit.Framework.CollectionAssert.AreEquivalent(IEnumerable expected, IEnumerable actual)
at CT.Tests.WpfControlsTests.ControlGeneratingMediator_AreDataProviderResultsPopulatingCorrectly_ReturnsTrue() in WPFControlsTests.cs: line 1338
NUnit.Framework.CollectionAssert.AreEquivalent方法的摘要声明:
&#34;断言预期和实际是等价的,包含相同的 对象但匹配可以按任何顺序排列。&#34;
由于集合中的对象源自不同的操作序列,因此我不确定是否要声明对象是相同的(或具有相同的散列);无论如何,我想声明对象具有匹配的属性值。我希望我不需要覆盖相等比较操作或执行一些疯狂的黑客来实现这一点。
这是负责任的测试:
using NUnit.Framework;
// . . .
[Test]
public void ControlGeneratingMediator_AreDataProviderResultsPopulatingCorrectly_ReturnsTrue()
{
var instance = SharedSetupSingleton.Instance;
var methodInfo = instance.GetMethodInfo();
SimpleLoadDynamicGridMediatorFactory factory = new SimpleLoadDynamicGridMediatorFactory();
var commandstrategymediator = factory.Build(SimpleMediatorFactory.MediatorType.LoadDynamicGridMediator_Simple, methodInfo);
var commandstrategymediatorConverted = (LoadDynamicGridMediator)commandstrategymediator;
commandstrategymediatorConverted.CallStrategy(methodInfo); // we really shouldn't need to pass in the methodInfo when it's already defined during construction.
var newMediator = factory.Build(SimpleMediatorFactory.MediatorType.ControlGeneratingMediator_Simple, methodInfo);
newMediator.CallStrategy();
//newMediator.InputCommandStrategyMediator = commandstrategymediatorConverted;
var originalResultList = new List<dynamic>();
// each item should be of type: {CT_EntityDataModel.PROC_CT_Select_udfFacilityHolds_Global_Result}
// I used the following foreach loops to work around an "InvalidOperationException: The result of a query cannot be enumerated more than once."
foreach (var item in commandstrategymediatorConverted.ProviderResultSet)
{
originalResultList.Add(item);
}
var mappedResultList = new List<dynamic>();
foreach (var item in newMediator.Strategy.Results)
{
mappedResultList.Add(item);
}
CollectionAssert.AreEquivalent(originalResultList, mappedResultList);
// Are both of these parameters pulling on the same IEnumerable?
//Assert.AreEqual(commandstrategymediatorConverted.ProviderResultSet, newMediator.Strategy.Results);
}
(注意:从最佳实践的角度来看,我意识到这个测试相当丑陋,看起来更像是集成测试,而不是实际的单元测试。如果你想批评测试,请提供一个代码示例,提供合理的改进(请记住,EF对象是在运行时解析的,因为我还没有找到一种动态调用它们的方法,同时仍保留生成的类型信息(即关于结果的类型信息)在编译时从一个通过实体框架调用的存储过程返回。如果你已经想出如何完成这个,那么请说些什么。(我想和你谈谈。))。< / p>
答案 0 :(得分:0)
有关公共财产价值比较,请参阅this answer。但它处理单个对象,因此您需要自己对集合进行循环。例如。按顺序在同一个字段中对每个条目进行排序,然后在同一索引的两个集合中依次访问每个条目并应用比较运算符。
请注意,本答案中的代码假定两个对象属于同一类型。修改它以接受两种不同的类型是相当简单的。
但是,可以说,您最好不要实现Equals
方法(例如,通过查看标识属性值),允许将其用于集合比较,然后使用单独的测试来检索一个对象通过两种机制,使用上面提到的方法比较每个机制的公共属性中的值,只是为了确保所有值都被填充。
答案 1 :(得分:0)
使用FluentAssertions(支持所有主要的单元测试框架),您可以执行此操作
originalResultList.ShouldAllBeEquivalentTo(mappedResultList);
断言这两个集合在结构上是等价的。