我有一个名为:requiredIf的自定义属性。此属性与名为RequiredIfValidator的自定义DataAnnotationsModelValidator相关。
我在Global.asax.cs文件中声明了这个映射:
DataAnnotationsModelValidatorProvider.RegisterAdapter( typeof( RequiredIfAttribute ), typeof( RequiredIfValidator ) );
在运行时它可以正常工作:)
但我想通过单元测试来测试我的模型的验证。猜猜比我们有以下
public class MyModel
{
public bool A {get;set;}
[RequiredIf ("A", true)]
public bool? B {get;set;}
}
当A为假时,此模型有效,当A为真时,B需要设置为true或false。
我尝试使用以下单元测试来测试此验证:
var viewModel = new MyModel();
var context = new ValidationContext( viewModel, null, null );
var results = new List<ValidationResult>();
viewModel.A = false;
var isModelStateValid = Validator.TryValidateObject( viewModel, context, results, true );
Assert.IsFalse( isModelStateValid );
断言失败了。这是因为我的RequiredIfValidator没有设置。所以我的问题是如何设置这个自定义验证器来运行我的单元测试?
谢谢,
答案 0 :(得分:0)
我设法通过以下扩展方法来使其工作:
public static class ViewModelExtensions
{
public static IReadOnlyCollection<ValidationResult> GetValidationResults<T>(this T viewModel, Func<Type, object> serviceProvider = null)
{
var result = GetComponentValidationResults(viewModel, serviceProvider);
var modelValidationResults = GetModelValidationResults(viewModel);
return result
.Concat(modelValidationResults.ToValidationResults())
.ToList();
}
private static List<ValidationResult> GetComponentValidationResults<T>(T viewModel, Func<Type, object> serviceProvider)
{
var vc = new ValidationContext(viewModel);
if (serviceProvider != null)
{
vc.InitializeServiceProvider(serviceProvider);
}
var result = new List<ValidationResult>();
Validator.TryValidateObject(viewModel, vc, result, true);
return result;
}
private static IEnumerable<ModelValidationResult> GetModelValidationResults<T>(T model)
{
var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(T));
/* build a stub controller context */
var controllerContext = Fake.ControllerContext.Build();
var validator = ModelValidator.GetModelValidator(modelMetadata, controllerContext);
return validator.Validate(null);
}
private static IEnumerable<ValidationResult> ToValidationResults(this IEnumerable<ModelValidationResult> results)
{
return results.Select(r => r.ToValidationResult());
}
private static ValidationResult ToValidationResult(this ModelValidationResult result)
{
return new ValidationResult(result.Message, new[] {result.MemberName});
}
}
可以这样使用:
// arrange
var target = new MyViewModel();
// act
var actual = target.GetValidationResults(StubServiceProvider);
// assert
/* Assertions for whatever the expected validation failure might be */
注意:
Fake.ControllerContext.Build()
调用是一个工厂,它基于以下内容生成存根控制器上下文:https://stackoverflow.com/a/32672/90609