尝试测试Task时获得Moq异常

时间:2018-11-06 14:48:13

标签: c# .net unit-testing testing moq

我正在尝试在异步调用上使用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:'以下关于模拟的设置   'Mock <.Repository.IRepository:00000001>'不匹配:IRepository   repo => repo.CreateAsync(It.IsAny ())

回购看起来像这样

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

UseCase

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

我做错了什么或想念什么?

2 个答案:

答案 0 :(得分:1)

我们通常不必模拟接口方法,除非我在您的问题中遗漏某些东西,否则该方法不会返回任何方法。

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

答案 1 :(得分:1)

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

您应该更改单元测试以使用async&await运行测试方法,而不是剥离新线程。请注意,测试用例的签名从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();
    }
}