Тесты с использованием столбцов InMemoryDatabase и Identity, как бороться? - PullRequest
0 голосов
/ 10 апреля 2019

.Net Core 2.2 / EFC 2.2.3 / Pomelo.EntityFrameworkCore.MySql 2.2.0

Представьте, что у вас есть таблица с именем Colors с некоторыми предопределенными данными.

public void Configure(EntityTypeBuilder<Color> builder)
{
    builder.ToTable("Colors");
    builder.HasKey(r => r.Id).UseMySqlIdentityColumn();
    builder.Property(r => r.Name).IsRequired().HasMaxLength(255);
    builder.Property(v => v.RGB).IsRequired().HasMaxLength(7);
    builder.HasData(GetSeed());
}
private ICollection<Color> GetSeed()
{
    return new List<Color>()
    {
        new Color(){Id=1, Name="Black", RGB="#000"},
        new Color(){Id=2, Name="White", RGB="#fff"},
    }
}

Один из моих тестов - проверка CreateColorCommandHandler.Очень просто

var Context = CBERPContextFactory.Create();
var query = new CreateColorCommandHandler(Context);

var command = new CreateColorCommand();
command.Name= "Random color";
command.RGB = "#001122";

var colorId = await query.Handle(command, CancellationToken.None);

//Assert
Assert.IsInstanceOf<long>(colorId);
Assert.NotZero(colorId);

var cor = Context.Colors.Where(p => p.Id == colorId).SingleOrDefault();
Assert.NotNull(cor);
Assert.AreEqual(command.Name, cor.Name);
Assert.AreEqual(command.RGB, cor.RGB);

CBERPContextFactory.Destroy(Context);

//>>> Handle simply add a new entity without informing ID

Метод обработки

public async Task<long> Handle(CreateColorCommand request, CancellationToken cancellationToken)
{
    var entity = new Color
    {
        Name = request.Name,
        RGB = request.RGB,
    };

    _context.Colors.Add(entity);

    await _context.SaveChangesAsync(cancellationToken);

    return entity.Id;
}

Когда я запускаю этот тест, я получаю ошибку An item with the same key has already been added. Key: 1.Что означает, что InMemoryDatabase не имеет функции автоинкремента.

Я неправильно пишу тест?

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

Вероятно, я здесь упускаю какое-то очень простое правило.

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

InMemoryDatabase еще не имеет всех функций, и AUTO INCREMENT - один из тех, которые нуждаются в улучшениях: https://github.com/aspnet/EntityFrameworkCore/issues/6872

Не тот ответ, который я хотел , но пока он работает:очистите все семена перед тестированием.

    private static void Clear(this DbContext context)
    {
        var properties = context.GetType().GetProperties();

        foreach (var property in properties)
        {
            var setType = property.PropertyType;
            bool isDbSet = setType.IsGenericType && (typeof(DbSet<>).IsAssignableFrom(setType.GetGenericTypeDefinition()));
            if (!isDbSet) continue;
            dynamic dbSet = property.GetValue(context, null);
            dbSet.RemoveRange(dbSet);
        }
        context.SaveChanges();
    }
0 голосов
/ 10 апреля 2019

Я предполагаю, что проблема в следующей строке:

var Context = CBERPContextFactory.Create();

Возможно, вы используете один и тот же экземпляр контекста для нескольких тестов. Согласно документации Тестирование с InMemory :

Каждый метод тестирования задает уникальное имя базы данных, то есть каждый метод имеет свою собственную базу данных InMemory.

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

Если по-прежнему не работает, попробуйте установить значение ключа идентификации вручную, поскольку база данных InMemory может не поддерживать автоинкремент.

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