Moq: работает потоки с FluentValidation - PullRequest
0 голосов
/ 10 декабря 2018

Я использую FluentValidation для проверки запроса.Если проверка не пройдена, UseCaseHandler не должен вызываться.В пределах UseCaseHandler я использую IRepository, и это проверяется, чтобы увидеть, вызывается ли UseCaseHandler.

Валидатор запросов

 public class MyValidator: AbstractValidator<Request>
 {
     public MyValidator()
     {
         RuleFor(rq=> rq)
              .Cascade(CascadeMode.Continue);
         RuleFor(rq=> rq)
            .Must(property => property.id != default(Guid))
            .WithMessage(message => $"invalid id.")
            .WithName(member => nameof(member.Id));

      }
 }

Это тест

[Fact]
public async Task Test()
{
     Mock<IUnitOfWork> uowMock = new Mock<IUnitOfWork>();
     Mock<IRepository> repositoryMock = new Mock<IRepository>(MockBehavior.Strict);
     Mock<IValidator<Request>> validatorMock = new Mock<IValidator<Request>>(MockBehavior.Strict);

     var request = new Request
     {
        Id = Guid.NewGuid()
     };

     validatorMock
         .Setup(validator => validator.Validate(request))
         .Returns(new ValidationResult());

     repositoryMock
          .Setup(repo => repo.SaveAsync(It.IsAny<object>()))
          .Returns(Task.CompletedTask);

     var sut = new UseCase(uowMock.Object, repositoryMock.Object, validatorMock.Object);


     Func<Task> act = () => sut.UseCaseHandler(request);


     await act.Should().NotThrowAsync();
     repositoryMock.Verify(repo => repo.SaveAsync(It.IsAny<object>()), Times.Once);
 }

Я ищу написать тест, который будет проверять поток.

Если проверка не пройдена, тест должен завершиться неудачно, и SaveAsync не должен вызываться.

Если проверка прошла успешно, тест также должен пройти успешно, и SaveAsync должен быть вызван один раз.

Как написать тест?

UPDATE

Это определение класса варианта использования.

UseCaseHandlerProxy - базовый абстрактный класс, который действует как прокси

public class UseCase : UseCaseHandlerProxy<Request, Response>
{
    private readonly IRepository _repository;


    public UseCase(IUnitOfWork unitOfWork, IRepository repository, IValidator<Request> validator)
        : base(unitOfWork, validator)
    {
        _repository = repository
    }

    public override async Task<Response> UseCaseHandler(Request request)
    {
        Order order = new Order();

        order.Create();

        await _repository.SaveAsync(order);

        return new Response(order.Id);
    }
}

Это определение класса запроса

class Request
{
    public Guid Id { get; set; }
}

Ответ Te возвращает только тот же Id

Класс прокси

public abstract class UseCaseHandlerProxy<TRequest, TResponse> : IUseCaseHandler<TRequest, TResponse>
    where TRequest : IRequest
    where TResponse : Response
{
    private IValidator<TRequest> Validator { get; }
    protected internal IUnitOfWork UnitOfWork { get; }


    public UseCaseHandlerProxy(IUnitOfWork unitOfWork, IValidator<TRequest> validator)
    {
        Validator = validator;
        UnitOfWork = unitOfWork;
    }

    async Task<TResponse> IUseCaseHandler<TRequest, TResponse>.HandleAsync(TRequest request)
    {
        ValidationResult validationResult = await Validator.ValidateAsync(request);

        TResponse response;

        if (!validationResult.IsValid)
        {
            response = (TResponse)System.Activator.CreateInstance(typeof(TResponse));

            validationResult.Errors.ToList().ForEach(error => response.AddError(error.PropertyName, error.ErrorMessage));

            return response;
        }

        response = await UseCaseHandler(request);

        return response;
    }

    public abstract Task<TResponse> UseCaseHandler(TRequest request);
}

1 Ответ

0 голосов
/ 11 декабря 2018

Учитывая поток, который вы хотите проверить, я бы сказал, что вы вызываете не того участника.

Приведите sut к IUseCaseHandler<TRequest, TResponse>, чтобы получить доступ к HandleAsync, что и делает требуемый поток.

Например, следующее проверяет, что если не возникает ошибка проверки, которая вызывает хранилище, сохраните.

[Fact]
public async Task UseCase_Should_Save() {
    //Arrange
    Mock<IUnitOfWork> uowMock = new Mock<IUnitOfWork>();
    Mock<IRepository> repositoryMock = new Mock<IRepository>(MockBehavior.Strict);
    Mock<IValidator<Request>> validatorMock = new Mock<IValidator<Request>>(MockBehavior.Strict);

    var request = new Request {
        Id = Guid.NewGuid()
    };

    validatorMock
        .Setup(validator => validator.ValidateAsync(request, It.IsAny<CancellationToken>()))
        .ReturnsAsync(new ValidationResult());

    repositoryMock
         .Setup(repo => repo.SaveAsync(It.IsAny<object>()))
         .Returns(Task.FromResult((object)null));

    var sut = new UseCase(uowMock.Object, repositoryMock.Object, validatorMock.Object) as IUseCaseHandler<Request, Response>;

    //Act
    Func<Task> act = () => sut.HandleAsync(request);

    //Assert
    await act.Should().NotThrowAsync();
    repositoryMock.Verify(repo => repo.SaveAsync(It.IsAny<object>()), Times.Once);
}

Следующее проверяет, что если есть ошибки, то хранилище не сохраняет

[Fact]
public async Task UseCase_Should_Not_Save() {
    //Arrange
    var uowMock = new Mock<IUnitOfWork>();
    var repositoryMock = Mock.Of<IRepository>();
    var validatorMock = new Mock<IValidator<Request>>(MockBehavior.Strict);

    var request = new Request {
        Id = Guid.NewGuid()
    };

    var result = new ValidationResult();
    result.Errors.Add(new ValidationFailure("SomeProperty", "SomeError"));

    validatorMock
        .Setup(validator => validator.ValidateAsync(request, It.IsAny<CancellationToken>()))
        .ReturnsAsync(result);

    var sut = new UseCase(uowMock.Object, repositoryMock, validatorMock.Object) as IUseCaseHandler<Request, Response>;

    //Act
    Func<Task> act = () => sut.HandleAsync(request);

    //Assert
    await act.Should().NotThrowAsync();
    Mock.Get(repositoryMock).Verify(repo => repo.SaveAsync(It.IsAny<object>()), Times.Never);
}
...