ServiceStack和FluentValidation不会触发单独的规则集

时间:2017-10-12 17:17:33

标签: servicestack fluentvalidation

我在ServiceStack工作并使用FluentValidation来处理请求中的传入DTO。我已按照以下方式解决了这些问题,但我的单元测试似乎无法针对特定的规则集。我的代码如下:

DTO / REQUEST CLASSES

public class VendorDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class DvrDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public VendorDto Vendor { get; set; }
}

public class DvrRequest : IReturn<DvrResponse>
{
    public DvrDto Dvr { get; set; }
}

验证员类

public class VendorValidator : AbstractValidator<VendorDto>
{
    public VendorValidator()
    {
        RuleFor(v => v.Name).NotEmpty();
    }
}

public class DvrValidator : AbstractValidator<DvrDto>
{
    public DvrValidator()
    {
        RuleFor(dvr => dvr.Name).NotEmpty();
        RuleFor(dvr => dvr.Vendor).NotNull().SetValidator(new VendorValidator());
    }
}

public class DvrRequestValidator : AbstractValidator<DvrRequest>
{
    public DvrRequestValidator()
    {
        RuleSet(HttpMethods.Post, () =>
        {
            RuleFor(req => req.Dvr).SetValidator(new DvrValidator());
        });

        RuleSet(HttpMethods.Patch, () =>
        {
            RuleFor(req => req.Dvr).SetValidator(new DvrValidator());
            RuleFor(req => req.Dvr.Id).GreaterThan(0);
        });
    }
}

UNIT TEST

[TestMethod]
public void FailWithNullDtoInRequest()
{
    // Arrange
    var dto = new DvrRequest();
    var validator = new DvrRequestValidator();

    // Act
    var result = validator.Validate(msg, ruleSet: HttpMethods.Post);

    // Assert
    Assert.IsTrue(result.IsValid);
}

我希望能够控制被调用的内容,具体取决于HttpMethod被调用的内容。我的想法是,我想验证DvrDto(和子VendorDto)上POST和PATCH的所有字段,但只需要在PATCH上设置有效的Id。我正在设置我的DvrRequestValidator来处理这个问题。但是,我上面写的单元测试(针对POST动词的RuleSet)总是发现请求有效,即使验证器应该使请求失​​败。

在摆弄它时,如果我做出以下更改:

VALIDATOR

public class DvrRequestValidator : AbstractValidator<DvrRequest>
{
    public DvrRequestValidator()
    {
        RuleFor(req => req.Dvr).SetValidator(new DvrValidator());

        RuleSet(HttpMethods.Patch, () =>
        {
            RuleFor(req => req.Dvr.Id).GreaterThan(0);
        });
    }
}

TEST CALL (删除目标动词)

    // Act
    var result = validator.Validate(msg); // , ruleSet: HttpMethods.Post);

验证器然后按照我期望的POST工作,但PATCH规则集不会被执行。结果,我似乎失去了我想要在特定动词上验证的粒度。在我看来,这在我在StackOverflow和FluentValidation文档中看到的示例中都得到了支持。我在这里做错了吗?或者这不可能吗?

1 个答案:

答案 0 :(得分:0)

验证程序在ServiceStack的全局请求筛选器中注册,因此您通常使用Integration Test和服务客户​​端来测试验证错误。

如果要在单元测试中独立测试验证器,可以使用以下内容执行HTTP方法结果集:

var req = new BasicRequest(requestDto);
var validationResult = validator.Validate(new ValidationContext(requestDto, null, 
    new MultiRuleSetValidatorSelector(HttpMethods.Patch)) {
        Request = req
    });

单元测试ServiceStack功能

虽然注意到许多ServiceStack功能都假定AppHost可用,但在大多数情况下,您只能使用In Memory AppHost,例如:

[Test]
public void My_unit_test()
{
    using (new BasicAppHost().Init())
    {
        //test ServiceStack classes
    }
}

如果您愿意,可以在每个测试夹具上设置一次,例如:

public class MyUnitTests
{
    ServiceStackHost appHost;
    public MyUnitTests() => appHost = new BasicAppHost().Init();

    [OneTimeTearDown]
    public void OneTimeTearDown() => appHost.Dispose();

    [Test]
    public void My_unit_test()
    {
        //test ServiceStack classes
   }
}