繁体   English   中英

如何设置具体的表达式<func<tentity, bool> &gt; 通过 Moq 在单元测试中进行模拟? </func<tentity,>

[英]How to set up a concrete Expression<Func<TEntity, bool>> to a mock in a unit test through Moq?

我的存储库中有以下方法:

  Task<TEntity> FirstOrDefaultAsync(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        CancellationToken cancellationToken = default);

我通过以下方式在服务中调用它:

 var itemToUpdate = await _unitOfWork.ItemsRepository
                .FirstOrDefaultAsync(x => x.Id == itemDto.Id && x.UserId == userId);

问题是如何在单元测试中调用它? 我对 ItemsRepository 有一个严格的模拟,当我这样调用它时,我得到一个异常,它是一个严格的模拟并且没有为我的场景设置:

            ItemsRepositoryMock
            .Setup(x => x.FirstOrDefaultAsync(x => x.Id == 1 && x.UserId == "ab70793b-cec8-4eba-99f3-cbad0b1649d0", null, CancellationToken.None))
            .ReturnsAsync(firstItem);

我应该如何使用我想要的参数设置模拟?

简短的回答是你不能直接在 Moq 中设置它。 原因是就 c# 而言,这些表达式不相等。

你能做什么...

  1. 是编写您自己的表达式比较,并且根据该表达式中允许的内容,它可能更容易或更难。 你设置模拟

    It.Is<Expression<Func<TheEntity, bool>>(actual=>CompareExpressions(actual, x=>x => x.Id == 1 && x.UserId == "ab70793b-cec8-4eba-99f3-cbad0b1649d0")

并实施

CompareExpressions<TEntity>(Func<TEntity, bool> actual,Func<TEntity, bool> expected)

遍历表达式树并在检测到差异时执行 Assert.Fail 并不是那么困难,但如果您之前没有这样做过,这可能是一个挑战,特别是如果您希望允许等效而不相同的表达式。 开始的好点是: ExpressionComparison

  1. 或者你可以编译表达式并用你可以做的匹配元素调用它

    It.Is<Expression<Func<TheEntity, bool>>(actual=>CompareExpressions(actual, new[]{ new Sample<TheEntity>{ Subject= new TheEntity{ /*...*/ }, Expected = true, new Sample /*...*/ ) CompareExpressions(Func<TEntity, bool> actual, List<TEntity> samples) { var method = actual.Compile(); foreach(var sample in sampes) Assert.AreEqual(sample.Expected, method(sample.Subject)); }

第二种方法更容易,但如果您准备的样本不够好,则可能会出现误报。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM