在这个类库中(针对.NET标准2.0和.NET Framework4.6.1),我在数据上下文级别进行数据验证,因为这些类可能被非web应用程序使用,所以我在静态帮助器类中遵循https://github.com/dotnet/efcore/issues/9662的示例:
internal static ICollection<ValidationResult> ValidateChanges(DbContext context)
{
var modifiedEntries = context.ChangeTracker.Entries()
.Where(x => x.State == EntityState.Added ||
x.State == EntityState.Modified);
List<ValidationResult> validationResults = new List<ValidationResult>();
foreach (var entry in modifiedEntries)
{
var validationContext = new ValidationContext(entry);
Validator.TryValidateObject(entry, validationContext, validationResults, true);
}
return validationResults;
}我的POCO (简化):
public class Person
{
[Required]
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
// other properties
}我的单元测试(简化):
[Fact]
public void TestDataValidation()
{
IPersonService svc = _container.Resolve<IPersonService>();
Person p = svc.Get(1);
string origValue = p.FirstName;
p.FirstName = string.Empty;
try
{
Assert.Throws<ValidationException>(() => svc.Update(p, p.Id));
}
catch (Xunit.Sdk.XunitException) // ValidationException not thrown
{
// restore original value
throw;
}
}服务类方法:
public virtual TEntity Update(TEntity entity, TKey key)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
((IDatabaseContext)Context).BeginTransaction();
TEntity dbEntity = Get(key);
Context.Entry(dbEntity).CurrentValues.SetValues(entity);
((IDatabaseContext)Context).Commit();
return entity;
}Commit()方法:
public abstract class DatabaseContext<TContext> : DbContext, IDatabaseContext
where TContext : DbContext
{
public void Commit()
{
ICollection<ValidationResult> validationResults = DbContextHelper.ValidateChanges(this);
if (validationResults.Count > 0)
{
foreach (ValidationResult validationResult in validationResults)
{
string message = string.Format("{0}: {1}", string.Join(", ", validationResult.MemberNames.ToArray()), validationResult.ErrorMessage);
throw new ValidationException(message);
}
}
base.Commit();
}
}当我执行测试时,验证完成失败。当我在验证方法的foreach循环中间放置一个断点时,我看到的是:
modifiedEntries有一个条目(因为expected)entry.CurrentValues["FirstName"]是一个空字符串)(当expected)entry.CurrentValues.Properties[5]显示{Property: Person.FirstName (string) Required} (似乎right)validationContext.Items显示Count = 0 )(等等,什么?这不应该是吗?
然后,当我到达验证方法的末尾时,validationResults是空的,尽管其中肯定有一些东西。
根据Data annotations attributes not working in asp net core,您需要在ServiceCollection上使用AddDataAnnotations(),但这是在ASP.NET MVC核心中实现的。对于我的单元测试应用程序,有类似的事情需要做吗?我还有什么遗漏吗?
提前感谢
发布于 2021-10-22 22:33:57
你可以试试这样的东西
//Assert
foreach (var item in ValidateModel(itemToCreate))
{
if(!string.IsNullOrEmpty(item.ErrorMessage)) throw new ValidationException(item.ErrorMessage);
}
/////
private static IList<ValidationResult> ValidateModel(object model)
{
var validationResults = new List<ValidationResult>();
var ctx = new ValidationContext(model, null, null);
Validator.TryValidateObject(model, ctx, validationResults, true);
return validationResults;
}https://stackoverflow.com/questions/65398511
复制相似问题