如何将 mockRepository return 方法设置为 return IEnumerable<T>?

How can I setup the mockRepository return method to return an IEnumerable<T>?

我是最小起订量的新手,之前我已经完成了一些编码,但这次我需要 return 我创建的任务列表中的 2 个对象。我尝试使用 mockRepository.SetReturnsDefault() 命令,但不知何故它不能像我编程的那样工作。我正在使用这个创建两个不同任务的测试,我只需要更新我创建的第一个任务 (taskPrev)。

我创建了一个处理程序来处理异常,这样我就不能创建与其他任务和其他业务规则重叠的任务,并且该测试我正在尝试更新以前的任务并且应该 return 成功但是当我 运行 测试它时 return 我添加到列表任务的所有任务,即使我正在使用一个函数来过滤这些任务。

我用来过滤的部分是 var tasks = await _repository.FindBy(x => x.Id != command.Id); 但它只是 return 所有两个任务而没有过滤它。

我想知道我是否以错误的方式使用最小起订量,或者是其他原因,因为我已经搜索了很多 fo运行,但没有找到任何可以帮助我的东西。

这是我将最小起订量配置为 return 列表的方式:

//Criar 1ª Task
Task taskPrev = new Task(taskTypeId, projectId, costCenterId, Convert.ToDateTime(date), 
        startHour, startMinute, endHour, endMinute, workItem, timeSheetId, description);
taskPrev.Id = taskId;
//Criar 2ª Task
Task taskCurr = new Task(taskTypeId, projectId, costCenterId, Convert.ToDateTime(date), 
        endHour, startMinute, Convert.ToByte(endHour + 1), endMinute, workItem, timeSheetId, description);
taskCurr.Id = taskId + 1;

List<Task> tasks = new List<Task>();
tasks.Add(taskPrev);
tasks.Add(taskCurr);
// mockRepository.SetReturnsDefault(System.Threading.Tasks.Task.FromResult((IEnumerable<Task>)tasks));
mockRepository.Setup(x => x.FindBy(x => It.IsAny<IAsyncRepository<Task>>())).Returns(System.Threading.Tasks.Task.FromResult((IEnumerable<Task>)tasks.Where(x => x.Id == taskCurr.Id)));

使用mockRepository.SetReturnsDefault() return两个任务并且不过滤; 使用 mockRepository.SetReturnsDefault()mockRepository.Setup() 与仅使用 SetReturnsDefault() 相同; 并且只使用 mockRepository.Setup() return 空.

我正在使用的测试代码:

[Theory]
[InlineData(1,1,1,"2020-03-25",9,0,10,0,"",1,"valor",1,5)]
[InlineData(2,2,2,"2020-03-28",11,0,12,0,"Valor",2,"valor",3,6)]
[InlineData(3,4,5,"2020-03-04",13,0,14,0,"",6,"valor",7,7)]
//Deve permitir editar uma task criada anteriormente a nova task
//EX: 1ª task finaliza as 10:00 e a nova inicia as 10:00, deve permitir uma alteração da 1ª task
public async void Update_PreviousTask_Return_Success_When_CurrentTask_HasStartHour_Equals_PreviousTask_EndHour(
    int taskTypeId, int projectId, int costCenterId, string date, byte startHour, byte startMinute,
    byte endHour, byte endMinute, string workItem, int timeSheetId, string description, int employeeId, int taskId)
    {
        //São necessários apenas para criação do handler
        var mockRepository = new  Mock<IAsyncRepository<Task>>();
        var mockRepositoryTimeSheet = new  Mock<IAsyncRepository<TimeSheet>>();
        var mockRepositoryProject = new  Mock<IAsyncRepository<Project>>();            

        //Cria handler
        TaskHandler handler = new TaskHandler(mockRepository.Object, 
        mockRepositoryTimeSheet.Object, mockRepositoryProject.Object);

        //Cria Project
        Project project = new Project("nameProject", 1, true, 1);
        project.Id = projectId;

        // List<Project> projects =new List<Project>();
        // projects.Add(project);
        mockRepositoryProject.SetReturnsDefault(System.Threading.Tasks.Task.FromResult(project));   

        //Cria timeSheet 
        TimeSheet timeSheet = new TimeSheet(1, Convert.ToDateTime(date).AddDays(-30), Convert.ToDateTime(date).AddDays(30), employeeId);
        timeSheet.Id = timeSheetId;

        List<TimeSheet> timeSheets = new List<TimeSheet>();
        timeSheets.Add(timeSheet);
        mockRepositoryTimeSheet.SetReturnsDefault(System.Threading.Tasks.Task.FromResult((IEnumerable<TimeSheet>)timeSheets));

        //Criar 1ª Task
        Task taskPrev = new Task(taskTypeId, projectId, costCenterId, Convert.ToDateTime(date), 
                startHour, startMinute, endHour, endMinute, workItem, timeSheetId, description);
        taskPrev.Id = taskId;
        //Criar 2ª Task
        Task taskCurr = new Task(taskTypeId, projectId, costCenterId, Convert.ToDateTime(date), 
                endHour, startMinute, Convert.ToByte(endHour + 1), endMinute, workItem, timeSheetId, description);
        taskCurr.Id = taskId + 1;

        List<Task> tasks = new List<Task>();
        tasks.Add(taskPrev);
        tasks.Add(taskCurr);
        // mockRepository.SetReturnsDefault(System.Threading.Tasks.Task.FromResult((IEnumerable<Task>)tasks));
        mockRepository.Setup(x => x.FindBy(x => It.IsAny<IAsyncRepository<Task>>())).Returns(System.Threading.Tasks.Task.FromResult((IEnumerable<Task>)tasks.Where(x => x.Id == taskCurr.Id)));

        //Command para criar a task
        UpdateTaskCommand command = new UpdateTaskCommand(taskTypeId, projectId, costCenterId, Convert.ToDateTime(date),
        startHour, startMinute, endHour, endMinute, workItem, "descrição Teste", taskId, employeeId);

        //Act
        var retorno = (CommandResult)await handler.Handle(command);

        //Assert
        Assert.True(retorno.Sucess);
        }

处理程序部分没有正常工作:

var tasks = await _repository.FindBy(x => x.Id != command.Id);
var retorno = tasks.FirstOrDefault(x => (x.TimeSheetId == command.TimeSheetId && x.Date.Date == command.Date.Date)
                                         &&
                                         (
                                             (
                                                 (new TimeSpan(x.StartHour, x.StartMinute, 0) <= new TimeSpan(command.StartHour, command.StartMinute, 0))
                                              && (new TimeSpan(x.EndHour, x.EndMinute, 0) > new TimeSpan(command.StartHour, command.StartMinute, 0))
                                              )
                                              ||
                                              (
                                                 (new TimeSpan(x.EndHour, x.EndMinute, 0) >= new TimeSpan(command.EndHour, command.EndMinute, 0))
                                              && (new TimeSpan(x.StartHour, x.StartMinute, 0) < new TimeSpan(command.EndHour, command.EndMinute, 0))
                                              )
                                              ||
                                              (
                                                 (new TimeSpan(x.StartHour, x.StartMinute, 0) >= new TimeSpan(command.StartHour, command.StartMinute, 0))
                                              && (new TimeSpan(x.EndHour, x.EndMinute, 0) <= new TimeSpan(command.EndHour, command.EndMinute, 0))
                                              )

                                         ));

if (retorno != null)
    throw new BusinessException("Não é permitido criar novos registros que se sobreponham a outros existentes", 
                                nameof(command.StartHour) + ", " + nameof(command.StartMinute) + ", " +
                                nameof(command.EndHour) + ", " + nameof(command.EndMinute), ErrorsEnum.ResourceInvalidField);

我认为您对如何在 Setup 方法中定义预期参数感到困惑。

为了说明问题,让我们看一下不涉及 lambda 的设置:

var myMock = new Mock<IMyThing>();
myMock.Setup(m => m.GetById(7)).Returns(new Thing());

这是调用 GetById 的设置,其中参数恰好为 7。如果您正在测试的代码调用 GetById(7),它将获得一个 Thing 对象。如果调用代码传递的不是 7,则不会匹配设置,并且 return 将为空。

您可以使用 It.IsAny():

使您的设置更加灵活
var myMock = new Mock<IMyThing>();
myMock.Setup(m => m.GetById(It.IsAny<int>())).Returns(new Thing());

现在,您的调用代码传递给 GetById() 的整数无关紧要 - 设置将始终匹配,并且您将始终得到一个非空的事物。

理解到位后,让我们看看您的设置:

mockRepository.Setup(x => x.FindBy(x => It.IsAny<IAsyncRepository<Task>>())).Returns(//stuff);

FindBy 方法采用 Func<Task,bool> 类型的谓词,您在这里提供了一个特定的谓词:x => It.IsAny<IAsyncRepository<Task>>()。因为您提供了一个特定的参数值,所以调用代码必须与该特定参数完全匹配,否则设置将不匹配。您的调用代码传递给 FindBy 的谓词不匹配,因为 (x => x.Id != command.Id) != (x => It.IsAny<IAsyncRepository<Task>>()),并且由于设置不匹配,您 return null(或者如果已调用 SetReturnsDefault,它将 return 无论默认 return 是什么。

如果您希望您的设置匹配您的调用代码可能发送的任何 lambda,它应该如下所示:

mockRepository.Setup(x => x.FindBy(It.IsAny<Func<Task,bool>>())).Returns(//stuff);