我在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文档中看到的示例中都得到了支持。我在这里做错了吗?或者这不可能吗?
答案 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功能都假定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
}
}