Moq:使用FluentValidation运行流

时间:2018-12-10 17:27:42

标签: c# unit-testing testing moq fluentvalidation

我正在使用FluentValidation验证请求。如果验证失败,则# Generator def gen(): for val in range(10): while True: val = yield val if val is None: break # Generator Wrapper class Pushable: def __init__(self, g): self.g = g self._next = None def send(self, x): if self._next is not None: raise RuntimeError("Can't pushback twice without pulling") self._next = self.g.send(x) def __iter__(self): try: while True: # Have to clear self._next before yielding if self._next is not None: (tmp, self._next) = (self._next, None) yield tmp else: yield next(self.g) except StopIteration: return # Calling code num_pushed = 0 f = Pushable(gen()) for x in f: print(x) if (x == 5) and (num_pushed in [0,1,2]): f.send(x) num_pushed += 1 不应该被调用。在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));

      }
 }

我正在寻找写一个可以检查流程的测试。

如果验证失败,则测试将失败,并且不应调用SaveAsync。

如果验证成功,则测试也应该成功,并且SaveAsync应该被调用一次。

编写测试的方式是什么?

更新

这是用例类定义。

[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); } 是充当代理的基本抽象类

UseCaseHandlerProxy

这是Request类的定义

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

Te响应仅返回相同的ID

代理类

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

1 个答案:

答案 0 :(得分:2)

鉴于您要测试的流程,我会说您正在调用错误的成员。

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