单元测试-模拟对象中的Lambda表达式产生意外结果

时间:2019-03-04 21:11:53

标签: c# unit-testing lambda moq xunit

我正在编写一些单元测试。我编写的其中一项测试具有意外行为,我对确切发生的事情感到困惑。问题在于嘲笑GetAsync方法。当我使用像limit这样的变量时,代码无法正常工作,但是如果我使用const而不是变量,则可以正常工作。这是我的源代码:

namespace TestClass
{
    public class LambdaTest<T> where T : TestModel
    {
        readonly List<T> _list = new List<T>();
        public virtual IEnumerable<T> GetAsync(Expression<Func<T, bool>> predicate)
        {
            return _list.AsQueryable().Where(predicate).Where(x => !x.IsDeleted).ToList();
        }

        public IEnumerable<T> TestMethod()
        {
            int limit = 100;
            var result = GetAsync(p => !p.IsDeleted && (DateTime.Now - p.CreationDate).TotalHours < limit);
            return result;
        }
    }

    public class TestModel
    {
        public long Id { get; set; }
        public bool IsDeleted { get; set; }
        public DateTime CreationDate { get; set; }
    }
}

测试项目:

namespace TestClass.Tests
{
    public class ExpressionTest
    {
        [Fact]
        public void SimpleTest()
        {
            var returnValue = new List<TestModel>
            {
                new TestModel() {CreationDate = DateTime.Now, Id = 1},
                new TestModel() {CreationDate = DateTime.Now, Id = 2}
            };
            var sut = new Mock<LambdaTest<TestModel>>();
            int limit = 100;
            sut.Setup(x => x.GetAsync(p => !p.IsDeleted && (DateTime.Now - p.CreationDate).TotalHours < limit))
               .Returns(returnValue);

            var result = sut.Object.TestMethod();

            Assert.True(true);
        }
    }
}

我不能在这里使用const。我知道表达树和与此问题有关的其他主题,但是谁能解释这里到底发生了什么以及如何解决这个问题?

我将不胜感激。

1 个答案:

答案 0 :(得分:1)

最后,我解决了这个问题。我通过如下方式模拟了方法的行为:

sut.Setup(x => x.GetAsync(
                It.IsAny<Expression<Func<TestModel, bool>>>()
            ))
            .Returns((Expression<Func<TestModel, bool>> predict) =>
            {
                var result = _list.Where(predict.Compile());
                return Task.FromResult(result);
            });