我是MOQ的新手,之前已经做了一些编码,但这次我需要在我创建的List of Tasks上返回2个对象。我试着使用mockRepository.SetReturnsDefault()命令,但不知何故,它就是不按我的编程方式工作。我正在使用这个测试来创建两个不同的Tasks,我只需要更新我创建的第一个Tasks(taskPrev)。
我创建了一个处理程序来制造异常,这样我就不能创建与其他任务和其他业务规则相重叠的任务,而且我试图更新以前的任务,应该返回成功,但当我运行测试时,它返回所有我添加到列表任务的任务,即使我使用一个函数来过滤这些任务。
我用来过滤的部分是 var tasks = await _repository.FindBy(x => x.Id != command.Id)。 但它只是返回所有的两个任务,没有过滤。
我想知道是我使用moq的方式不对还是其他原因,因为我已经搜索了很多foruns,但没有找到任何可以帮助我的方法。
下面是我配置moq返回列表的方法。
//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() 同时返回两个任务,不过滤;使用 mockRepository.SetReturnsDefault() 和 mockRepository.Setup() 和只使用SetReturnsDefault()一样;而只使用 mockRepository.Setup() 返回空。
我正在使用的测试代码。
[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方法中定义预期参数的方式有些混乱。
为了说明这个问题,我们来看一个不涉及lambdas的设置。
var myMock = new Mock<IMyThing>();
myMock.Setup(m => m.GetById(7)).Returns(new Thing());
这是一个调用GetById(7)的设置,参数正好是7。 如果你正在测试的代码调用GetById(7),它将得到一个Thing对象。 如果调用代码传递的不是7,那么设置将不匹配,返回的将是null。
你可以通过使用It.IsAny()让你的设置更加灵活。
var myMock = new Mock<IMyThing>();
myMock.Setup(m => m.GetById(It.IsAny<int>())).Returns(new Thing());
现在,不管你的调用代码传递给GetById()的是什么整数,设置总是会被匹配,你总是会得到一个非空的Thing。
有了这样的理解,我们来看看你的设置。
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>>())
,由于设置不匹配,你将返回null(或者如果调用了SetReturnsDefault,它将返回任何默认的返回值)。
如果你想让你的设置匹配你的调用代码可能发送的任何lambda,它应该像这样。
mockRepository.Setup(x => x.FindBy(It.IsAny<Func<Task,bool>>())).Returns(//stuff);