我有这样的接口(interface)和实现:
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 的新手,我不确定如何模拟 ITicketService
以便我可以控制 GetTicket
作为参数的内容,并且因此在这种情况下它会返回什么。
最佳答案
您可以使用Callback
来捕获传入的委托(delegate),然后调用它。
这将在一定程度上模拟实现的内部工作。
但实际上可以在 Returns
委托(delegate)中完成同样的操作
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;
});
关于c# - 如何正确模拟代表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62302248/