工作的LINQ查询在单元测试中无法正常工作

3

我有一个非常类似的查询:

var result = context.EntityRole
   .Where(er => er.EntityType.EntityTypeId == entityTypeIdParameter
                && er.Entity.SomeItems.Any(item => item.ItemId == itemIdParameter))
   .ToList()
   .Distinct(customItemComparer)
   .OrderBy(er => er.Id)
   .ThenByDescending(er => er.IsApproved)
   .ToList();

customItemComparer类似于以下内容:
public class CustomItemComparer : IEqualityComparer<EntityRole>
{
   public bool Equals(EntityRole x, EntityRole y)
   {
      if (ReferenceEquals(x, y)) return true;

      if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;

      return x.Property1 == y.Property1
             && x.Property2 == y.Property2
             && x.Property3 == y.Property3;
   }

   public int GetHashCode(EntityRole obj)
   {
      if (ReferenceEquals(obj, null)) return 0;

      var hasProperty1 = obj.Property1.GetHashCode();
      var hasProperty2 = obj.Property2.GetHashCode();
      var hasProperty3 = obj.Property3.GetHashCode();

      return hasProperyt1 ^ hasProperty2 ^ hasProperty3;
   }
}

我的问题是,当我运行应用程序时,我得到了预期的结果,显然所有不同的情况都运行良好,但是当我尝试单元测试时,查询始终返回单个对象,即使列表包含多个具有不同属性1、2和3的对象。

我的单元测试大致如下,我们使用MOQ,在此简化其他属性:

var roles = new List<EntityRole>
{
   new EntityRole
   {
      Property1 = true,
      Property2 = 5,
      Property3 = "something"
   },
   new EntityRole
   {
      Property1 = true,
      Property2 = 9,
      Property3 = "something"
   },
   new EntityRole
   {
      Property1 = false,
      Property2 = 5,
      Property3 = "something"
   },
   new EntityRole
   {
      Property1 = true,
      Property2 = 5,
      Property3 = "something else"
   }
}

contextMock.Setup(c => c.EntityRole).Returns(roles.AsQueryable);

var sut = new SubjectUnderTest();
sut.MethodWhereQueryIsExecuted();

//some code to verify results

就像我所说的那样,即使在列表中没有两个相同的对象,查询始终返回第一个对象。

此外,如果我在CustomItemComparer中设置断点,应用程序运行时会停止执行,但调试测试时却永远不会停止。

因此,确切的问题是:为什么Distinct在运行应用程序时完美地工作,而在运行单元测试时却不起作用?


2
你应该真正地构建查询,以便所有这些操作都在数据库中执行,而不是在应用程序内部执行。 - Servy
看起来你的最后一行代码 contextMock.Setup(c => c.EntityRole).Returns(roles.AsQueryable); 没有任何意义。Setup 方法应该模拟某个对象的方法,而 Returns 应该返回该方法的一些虚假结果。我没有看到你的 contextMock 调用了带有该查询的 db 查询或方法。 - rock_walker
@SergioRomero:不,我不是想要移除 ToList,而是想要移除之后的所有内容,以检查 WhereDistinct 是否过滤了其他项... - Christoph Fink
@ChrFin: 就像我说的一样,该应用程序完美地运行。如果我删除 Distinct,则所有对象都被返回,减去不符合 where 子句的对象,这与运行应用程序时相同。问题是为什么在单元测试中 Distinct 不起作用? - Sergio Romero
请提供一个最小完整的示例以展示问题,以便我们可以重现它。 - Mike Stockdale
显示剩余5条评论
1个回答

1
我在使用MOQ和Distinct时遇到了同样的问题,在生产环境中运行良好,但在测试中却失败了。看起来distinct对于类型为Mock<>.Object的对象不起作用。

在我的情况下,我选择使用MoreLINQ的DistinctBy扩展。如果您只想使用Linq,则可以使用GroupBy并取每个组的第一个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接