尝试测试任务时 Moq 出现异常

Getting exception with Moq when trying to test Task

我正在尝试在异步调用中使用 Moq (4.10),但我无法掌握它的窍门。

搜索如何执行此操作并找到我已尝试但无法正常工作的答案。

这是我的测试

 public class Test
 {
        [Fact]
        public void Test_Create()
        {
            var repositoryMock = new Mock<IRepository>();

            repositoryMock
             .Setup(repo => repo.CreateAsync(It.IsAny<Aggregate >()))
             .Returns(Task.CompletedTask); 
/// also tried this 
/// => .Returns(Task.FromResult(default(object))) 
/// and 
/// => .Returns(Task.FromResult(false))); 

            var useCase = new CreateUseCase(repositoryMock.Object);

            Task.Run(async () => { await useCase.HandleAsync(new CreateRequest()); });

            repositoryMock.VerifyAll();
        }
}

资源

How can I tell Moq to return a Task?

获取此异常

Moq.MockException: 'The following setups on mock 'Mock<.Repository.IRepository:00000001>' were not matched: IRepository repo => repo.CreateAsync(It.IsAny < Aggregate>())

回购看起来像这样

public interface IRepository 
{
    Task CreateAsync(Aggregate aggregate);
}

用例

    public class CreateUseCase : IUseCaseHandler<CreatRequest>
    {

        private IRepository _repository;


        public CreateUseCase (IRepository repository)
        {
            _repository= repository?? throw new System.ArgumentNullException(nameof(repository));
        }


         public async Task HandleAsync(CreateRequest request, CancellationToken? cancellationToken = null)
         {
              Aggregate aggregate = new Aggregate();
                        aggregate.Create();
              await _repository.CreateAsync(aggregate);
          } 
     }

存储库

 public sealed class OrderRepository : ProxyRepository<OrderAggregate>, IOrderRepository
    {
        public OrderRepository(IUnitOfWork unitOfWork, INotificationDispatcher eventHandler) 
            : base(unitOfWork, eventHandler)
        {
        }

        async Task IRepository.CreateAsync(Aggregate aggregate)
        {
            await base.AddAsync(aggregate); 
        }
    }

我做错了什么或遗漏了什么?

我们通常不必模拟没有 return 任何接口的方法,除非我在你的问题中遗漏了什么。

public class CreateUseCaseTests
{
    [Fact]
    public async Task HandleAsync_ShouldCreateRequest()
    {
        // Arrange
        var repositoryMock = new Mock<IRepository>();    
        var sut = new CreateUseCase(repositoryMock.Object);

        // Act
        await sut.HandleAsync(new CreateRequest());

        // Assert
        repositoryMock.Verify(x => x.CreateAsync(It.IsAny<Aggregate>()), Times.Once);
    }
}

我认为您的问题根本不在于最小起订量设置。问题是单元测试 运行 是使用 Task.Run() 的有意义的代码,它会产生一个新线程。然后回到原始线程,立即测试 Moq 设置是否已完成。由于被测代码是在不同的线程上启动的,因此很有可能在被测代码执行之前测试是否成功。

您应该将单元测试更改为 运行 使用异步和等待的测试方法,而不是分离出一个新线程。请注意,测试用例的签名从 void 更改为 async Task,并且我们 await 我们正在测试的代码。

public class Test
{
    [Fact]
    public async Task Test_Create()
    {
        var repositoryMock = new Mock<IRepository>();

        repositoryMock
             .Setup(repo => repo.CreateAsync(It.IsAny<Aggregate >()))
             .Returns(Task.CompletedTask); 

        var useCase = new CreateUseCase(repositoryMock.Object);

        await useCase.HandleAsync(new CreateRequest());

        repositoryMock.VerifyAll();
    }
}