如何正确模拟代表

问题描述 投票:1回答:1

我有一个接口和实现是这样的。

public interface IScopedServices
{
   Task<TReturn> ExecuteAsync<TService, TReturn>(Func<TService, Task<TReturn>> action);
}

//Implemented like so:

public async Task<TReturn> ExecuteAsync<TService, TReturn>(Func<TService, Task<TReturn>> action)
{
   using (var serviceScope = serviceScopeFactory.CreateScope())
   {
      var service = serviceScope.ServiceProvider.GetService<TService>();
      return await action.Invoke(service);
   }
}

这个服务包装了其他服务的调用 这样他们就可以得到自己的范围,这样的服务调用的例子是:

public class TicketService : ITicketService
{
   public async Task<Ticket> GetTicket(string ticketNumber)
   {
      return await repository.Get(t => t.TicketNumber == ticketNumber);
   }
}

而在我的测试代码中,这个调用是这样的。

var ticket = await ScopedServices.ExecuteAsync<ITicketService, Ticket>(s => s.GetTicket("ticket number"));

所以在我的单元测试中,我这样模拟它,它工作得很好,没有问题。

var mockScopedServices = new Mock<IScopedServices>();

mockScopedServices.Setup(mss => mss.ExecuteAsync(It.IsAny<Func<ITicketService, Task<Ticket>>>())).ReturnsAsync(TestTicket);

我的问题是: 我怎样才能模拟这个服务调用?ITicketService 以致于 GetTicket 用一个特定的参数调用它,我返回一个单独的对象?

现在,由于我是Moq的新手,我不知道如何模拟Moq中的 ITicketService 这样我就可以控制 GetTicket 作为一个参数,因此在这种情况下它会返回什么。

c# moq
1个回答
1
投票

你可以使用 Callback 来捕获传入的委托,然后调用它。

这在一定程度上是在嘲笑实现的内部工作。

但实际上,同样的事情也可以在 Returns 委托

var scopedMock = new Mock<ITicketService>();
scopedMock 
    .Setup(_ => _.GetTicket(It.IsAny<string>())) // <-- setup and adjust as needed
    .ReturnsAsync(TestTicket);

var mockScopedServices = new Mock<IScopedServices>();
mockScopedServices
    .Setup(_ => _.ExecuteAsync(It.IsAny<Func<ITicketService, Task<Ticket>>>()))
    .Returns((Func<ITicketService, Task<Ticket>> arg) => {
        //this invokes the passed in delegate using the mocked scoped service
        Task<Ticket> task = arg(scopedMock.Object);
        return task;
    });
© www.soinside.com 2019 - 2024. All rights reserved.