В этой библиотеке классов (ориентированной на .NET Standard 2.0 и .NET Framework 4.6.1) я выполняю проверку данных на уровне контекста данных, поскольку эти классы могут использоваться не веб-приложениями, поэтому я следую примеру из 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имеет один элемент (как и ожидалось)entry.CurrentValues["FirstName"]- пустая строка (как и ожидалось)- Когда вы просматриваете его в списке наблюдения отладчика,
entry.CurrentValues.Properties[5]показывает{Property: Person.FirstName (string) Required}(кажется правильным) validationContext.ItemsпоказываетCount = 0(подождите, что? Разве это не должно быть 1?)
Затем, когда я дойду до конца метода проверки, validationResults будет пустым, хотя там определенно должно быть что-то.
Согласно атрибуты аннотаций данных не работают в ядре asp net вам нужно AddDataAnnotations() в ServiceCollection, но это в ASP.NET MVC Core. Есть ли что-то подобное, что мне нужно сделать для моего приложения для модульного тестирования? Я что-то еще упускаю?
заранее спасибо