简体   繁体   English

使用 Entity Framework Core 在 xUnit 测试中验证 [Required] 属性失败

[英]Validation of [Required] attribute failing in xUnit test with Entity Framework Core

In this class library (targeting .NET Standard 2.0 and .NET Framework 4.6.1), I am doing data validation at the data context level, as these classes may be used by non-web applications, so I'm following the example from https://github.com/dotnet/efcore/issues/9662 in a static helper class: In this class library (targeting .NET Standard 2.0 and .NET Framework 4.6.1), I am doing data validation at the data context level, as these classes may be used by non-web applications, so I'm following the example from https: //github.com/dotnet/efcore/issues/9662在 static 助手 class 中:

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

My POCO (simplified):我的 POCO(简体):

public class Person
{
    [Required]
    public int Id { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    // other properties
}

My unit test (simplified):我的单元测试(简化):

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

The service class method:服务class方法:

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

The Commit() method: 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();
    }
}

When I execute the test, the validation complete fails.当我执行测试时,验证完成失败。 When I put a break point in the middle of the foreach loop of the validation method, this is what I see:当我在验证方法的 foreach 循环中间放置一个断点时,我看到的是:

  • modifiedEntries has one item (as expected) modifiedEntries有一项(如预期的那样)
  • entry.CurrentValues["FirstName"] is an empty string (as expected) entry.CurrentValues["FirstName"]是一个空字符串(如预期的那样)
  • When you view it in the debugger watch list, entry.CurrentValues.Properties[5] shows {Property: Person.FirstName (string) Required} (seems right)当您在调试器监视列表中查看它时, entry.CurrentValues.Properties[5]显示{Property: Person.FirstName (string) Required} (似乎正确)
  • validationContext.Items shows Count = 0 (wait, what? shouldn't this be 1?) validationContext.Items显示Count = 0 (等等,什么?这不应该是 1 吗?)

Then when I reach the end of the validation method, validationResults is empty, even though there definitely should be something in there.然后,当我到达验证方法的末尾时, validationResults是空的,即使其中肯定应该有一些东西。

According to Data annotations attributes not working in asp net core you need AddDataAnnotations() on the ServiceCollection, but that's in ASP.NET MVC Core.根据Data annotations attributes not working in asp net core ,您需要在 ServiceCollection 上使用AddDataAnnotations() ,但这是在 ASP.NET MVC Core 中。 Is there something similar I needed to do for my unit test application?我需要为我的单元测试应用程序做类似的事情吗? Am I missing anything else?我还缺少什么吗?

Thanks in advance提前致谢

You can try something like that你可以尝试类似的东西

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM