Должны ли столбцы аудита быть тестируемыми? - PullRequest
1 голос
/ 28 января 2020

Мне было поручено добавить столбцы аудита в таблицу c.

public interface IAuditedEntity
{
    DateTime CreatedAt { get; }
    DateTime LastUpdatedAt { get; }
}

public class MyEntity: IAuditedEntity
{
    private readonly DateTime _utcNow = DateTime.UtcNow;

    public DateTime CreatedAt { get => _utcNow; private set { } }
    public DateTime LastUpdatedAt { get => _utcNow; private set { } }
}

Я думал о заполнении значений путем переопределения SaveChangesAsync с использованием ChangeTracker.

* 1007. * Один из моих коллег считает, что эти значения должны быть тестируемыми, и я не уверен, как это можно сделать с помощью этой реализации.

Я также никогда не видел тестируемое автоматически сгенерированное поле, и мне интересно, что будет лучший подход для таких (или это требование имеет смысл вообще).

Ответы [ 3 ]

0 голосов
/ 28 января 2020

Полагаю, это немного зависит от того, что вы подразумеваете под сгенерированным автоматически. Я не уверен, как вы могли бы проверить их, если они были автоматически сгенерированы базой данных, но если вы заполните значения в методе SaveChangesAsync, то вы можете определить интерфейс для задачи, а затем смоделировать его в своем тесты. Что-то вроде

public interface IAuditSource
{
    public DateTime Now { get; }

    public string LoggedOnUser { get; }
}

public class AuditSource : IAuditSource
{
    public DateTime Now => DateTime.Now;

    public string LoggedOnUser => // however you authenticate
}


public class MyDbContext : DbContext
{
    private IAuditSource _auditSource;

    public MyDbContext(IAuditSource auditSource): base() {}

    public override int SaveChangesAsync()
    {
         // If Changed Entities are IAuditedEntity
         // Set values using _auditSource
    }
}


public void MyTestMethod()
{
    var auditSource = new Mock<IAuditSource>()
    auditSource.Setup(x => x.Now).Returns(new DateTime(2020, 01, 28))
    var context = new MyDbContext(auditSource.Object)
}
0 голосов
/ 28 января 2020

, хотя ни один ответ не удовлетворяет моим требованиям atm, в качестве временного решения я решил go со следующим

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyEntity>(entity =>
    {
        entity.Property(e => e.CreatedAt)
            .HasDefaultValueSql("GetUtcDate()")
            .ValueGeneratedOnAdd();
        entity.Property(e => e.LastUpdatedAt)
            .HasDefaultValueSql("GetUtcDate()")
            .ValueGeneratedOnAddOrUpdate();
    });

    base.OnModelCreating(modelBuilder);
}

, так как значения не вводятся в сущность вручную, нет необходимости Попробуй это. если придет лучший ответ, я бы подумал изменить его.

0 голосов
/ 28 января 2020

И CreatedBy, и LastUpdatedBy должны быть точно и точно определены в ваших тестовых примерах. Следовательно, я считаю, что оба могут быть утверждены в тестовых примерах.

Точно так же, если у вас нет каких-то странных временных требований, должно быть довольно легко наложить ограничения на поля CreatedAt и LastUpdatedAt.

Я бы также предложил, чтобы, если вы находитесь на EFCore, используйте базу данных в памяти для упрощения обратного просмотра и подтверждаете здесь.

var now = DateTime.Now;
repository.Insert(entity);

// At this point, I think both the entity itself and if you can read it back from the store should have acceptable values or the test fails.
Assert.IsTrue(entity.CreatedBy == "me");
Assert.IsTrue(entity.LastUpdatedBy == "me");
Assert.IsTrue((now - entity.CreatedAt).TotalMilliseconds <= tolerance);
Assert.IsTrue((now - entity.LastUpdatedAt).TotalMilliseconds <= tolerance);

var newEntity = repository.Get(entity.Id);
// same tests here.

// Repeat similarly for update, and ensure created attributes don't change.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...