使用Moq模拟带有Func <T,bool>参数的存储库调用

XN1*_*N16 1 c# moq mocking

我正在尝试使用Moq来模拟我的某些存储库调用,并且我产生的大多数单元测试都运行良好,但是我遇到了无法正确模拟的情况。

需要模拟的我的存储库调用具有以下签名:

IEnumerable<T> Get(
    Expression<Func<T, bool>> filter = null, 
    Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, 
    string includeProperties = "");
Run Code Online (Sandbox Code Playgroud)

我正在进行单元测试的方法如下:

public bool CheckForTaskUsage(int taskId)
{
    return _taskInstanceRepository.Get(x => x.Task.Id == taskId).Any();
}
Run Code Online (Sandbox Code Playgroud)

单元测试如下:

Task task_1 = new Task() { Id = 1 };
TaskInstance taskInstance_1 = new TaskInstance() { Id = 1, Task = task_1 };
_domainTaskInstances = new List<TaskInstance>() { taskInstance_1 };

[TestMethod()]
public void TaskService_CheckForTaskUsage_Success()
{
    int taskId = 1;
    //_taskInstanceRepository.Setup(x => x.Get(y => y.Task.Id == taskId,null,""))
    //    .Returns(_domainTaskInstances);
    _taskInstanceRepository.Setup(x => x.Get(null, null, ""))
        .Returns(_domainTaskInstances);
    bool expected = true;
    bool actual;
    actual = GetTarget().CheckForTaskUsage(taskId);
    Assert.AreEqual(expected, actual);
}
Run Code Online (Sandbox Code Playgroud)

无论如何,由于CheckForTaskUsage返回false 的调用导致测试失败,正如您_domainTaskInstances应用于Moq设置所看到的那样,这是不正确的。我已经逐步完成了代码,它应该可以正常工作,并且可以通过UI正常工作。

然后,我尝试实际尝试重新创建该方法中Func<>使用的CheckForTaskUsage方法(您可以在单元测试中看到此尝试被注释掉),即使签名和变量应该相同,这仍然失败。

最后,作为测试,我尝试将CheckForTaskUsage方法内容修改为以下内容:

return _taskInstanceRepository.Get().Where(x => x.Task.Id == taskId).Any();
Run Code Online (Sandbox Code Playgroud)

这允许测试成功通过,但是我不想更改我的方法代码以允许单元测试通过!

我认为问题在于我需要Func<>像尝试的那样重新创建参数,但是我不知道我在这里做错了什么,任何建议都会受到欢迎!

谢谢

(ps,我知道这里没有全部代码(例如某些变量声明等),但是我知道这不是问题,因为该代码已在其他测试中使用并可以正常工作,这个问题很混乱。)

按照要求:

public TaskService GetTarget()
{
    return new TaskService(_taskRepository.Object);
}
Run Code Online (Sandbox Code Playgroud)

Jep*_*sen 5

我认为您应该这样做:

_taskInstanceRepository
    .Setup(x => x.Get(It.IsAny<Expression<Func<TaskInstance, bool>>>(), null, ""))
    .Returns(_domainTaskInstances);
Run Code Online (Sandbox Code Playgroud)

您测试的方法没有提供null第一个参数filter,它提供了的一些实例Expression<...>

显然,您不能在表达式中遗漏;的可选参数Setup;因此代码:

_taskInstanceRepository
    .Setup(x => x.Get(It.IsAny<Expression<Func<TaskInstance, bool>>>())) // illegal
    .Returns(_domainTaskInstances);
Run Code Online (Sandbox Code Playgroud)

这会显得有点更像是在你测试方法的语法,是不会允许的。