简体   繁体   English

如何设置 mockRepository 返回方法以返回 IEnumerable<t> ?</t>

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

I'm new to MOQ and I already done some coding before but this time I need to return 2 objects on a List of Tasks that I created.我是 MOQ 的新手,之前已经完成了一些编码,但这次我需要在我创建的任务列表中返回 2 个对象。 I tried using mockRepository.SetReturnsDefault() command but somehow it just don't work as the way I programmed to.我尝试使用 mockRepository.SetReturnsDefault() 命令,但不知何故,它不像我编程的那样工作。 I'm using this test that create two different Tasks and I just need to Update the first Tasks that I created (taskPrev).我正在使用这个创建两个不同任务的测试,我只需要更新我创建的第一个任务(taskPrev)。

I created a Handler to make the exceptions so that i can't create tasks that overlap others, and others business rules, and that Test i'm trying to Update a previous task and should return Sucess but when I run test it return all tasks that i added to the List tasks even when i'm using a function to filter those tasks.我创建了一个处理程序来进行例外处理,这样我就不能创建与其他任务和其他业务规则重叠的任务,并且我正在尝试更新以前的任务并且应该返回 Sucess 但是当我运行测试时它会返回所有任务即使我使用 function 过滤这些任务,我也添加到列表任务中。

The part that i'm using to filter is var tasks = await _repository.FindBy(x => x.Id.= command;Id);我用来过滤的部分是var tasks = await _repository.FindBy(x => x.Id.= command;Id); but it just return all the two tasks without filtering it.但它只是返回所有两个任务而不过滤它。

I'd like to know if i'm using the moq on the wrong way or is other thing because i already search for many foruns and didn't find anything that could help me.我想知道我是否以错误的方式使用最小起订量或其他原因,因为我已经搜索了很多论坛,但没有找到任何可以帮助我的东西。

Here is the way i'm configuring moq to return the list:这是我配置最小起订量以返回列表的方式:

//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)));

Using mockRepository.SetReturnsDefault() return both tasks and dont filter;使用mockRepository.SetReturnsDefault()返回两个任务并且不过滤; Using mockRepository.SetReturnsDefault() and mockRepository.Setup() makes the same as using only SetReturnsDefault();使用mockRepository.SetReturnsDefault()mockRepository.Setup()与仅使用 SetReturnsDefault(); 相同; And using only mockRepository.Setup() return empty.并且仅使用mockRepository.Setup()返回空。

The Test code that i'm using:我正在使用的测试代码:

[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);
        }

And the Handler part that is not working as it should be:以及无法正常工作的 Handler 部分:

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);

I think you have some confusion in how you're defining the expected parameter in your Setup method.我认为您对如何在 Setup 方法中定义预期参数有些困惑。

To illustrate the issue, let's look at a setup that doesn't involve lambdas:为了说明这个问题,让我们看一个不涉及 lambda 的设置:

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

This is a setup for a call to GetById where the parameter is exactly 7. If the code you are testing calls GetById(7), it will get a Thing object.这是调用 GetById 的设置,其中参数正好是 7。如果您正在测试的代码调用 GetById(7),它将得到一个 Thing object。 If the calling code passes anything other than 7, then the setup will not be matched, and the return will be null.如果调用代码传递的不是 7,则设置将不匹配,返回 null。

You can make your setup more flexible by using It.IsAny():您可以使用 It.IsAny() 使您的设置更加灵活:

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

Now it doesn't matter what integer your calling code passes to GetById() - the setup will always be matched, and you'll always get a non-null Thing.现在,调用代码传递给 GetById() 的 integer 无关紧要 - 设置将始终匹配,并且您将始终得到非空的事物。

With that understanding in place, let's look at your setup:有了这个理解,让我们看看你的设置:

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

The FindBy method takes a predicate of type Func<Task,bool> , and here you have provided a specific predicate: x => It.IsAny<IAsyncRepository<Task>>() . FindBy 方法采用Func<Task,bool>类型的谓词,在这里您提供了一个特定的谓词: x => It.IsAny<IAsyncRepository<Task>>() Because you provided a specific parameter value, then the calling code must either exactly match that specific parameter, or the setup won't be matched.因为您提供了特定的参数值,所以调用代码必须与该特定参数完全匹配,否则设置将不匹配。 The predicate your calling code is passing to FindBy does not match because (x => x.Id.= command.Id) != (x => It.IsAny<IAsyncRepository<Task>>()) , and since the setup is not matched, you return null (or if SetReturnsDefault has been called, it will return whatever the default return is).您的调用代码传递给 FindBy 的谓词不匹配,因为(x => x.Id.= command.Id) != (x => It.IsAny<IAsyncRepository<Task>>()) ,因为设置是不匹配,您返回 null (或者如果已调用 SetReturnsDefault,它将返回默认返回值)。

If you want your setup to match any lambda your calling code might send in, it should look like this:如果您希望您的设置与您的调用代码可能发送的任何 lambda 匹配,它应该如下所示:

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

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

相关问题 我怎样才能安全返回List <T> 从声明为IEnumerable的方法/属性 <T> ? - How can I safely return List<T> from method/property declared as IEnumerable<T>? 我如何返回IEnumerable <T> 从一种方法 - How do i return IEnumerable<T> from a method 我怎么能回来 <TEnumerable, T> :TEnumerable:IEnumerable <T> - How can I return <TEnumerable, T> : where TEnumerable:IEnumerable<T> 如何使异步方法返回任务<ienumerable<t> >? </ienumerable<t> - How do I make an async method return Task<IEnumerable<T>>? 如何从 Ienumerable 返回一个字符串? - How can I return a string from an Ienumerable? 如何返回一个空的 IEnumerable? - How can I return an empty IEnumerable? 为什么我不能返回任务<ienumerable<out t> > 无需让我的方法异步并使用 await </ienumerable<out> - Why can't I return a Task<IEnumerable<out T>> without making my method async and using await 为什么我不能返回IEnumerable <IGrouping<A,B> &gt;作为IEnumerable <IEnumerable<B> &gt; - Why can't I return an IEnumerable<IGrouping<A,B>> as an IEnumerable<IEnumerable<B>> 如何返回 IEnumerable<t> 作为 null</t> - How to return IEnumerable<T> as null 如何使方法返回IEnumerable <T> 从数组? - How to make a method return IEnumerable<T> from array?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM