使用InMemoryDatabase和Identity列进行测试,该如何处理?

时间:2019-04-09 23:48:56

标签: c# entity-framework unit-testing testing

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

想象一下,您有一个名为Colors的表,其中包含一些预定义的数据。

ffill

我的测试之一是测试CreateColorCommandHandler。非常直率

df = df.sort_values('Date').groupby(['WorkerID', 'Category']).ffill().sort_index()

df
    WorkerID Category       Date  Weight  Height  Kind_eat
Ind                                                       
1    E145-46      cat 2017-12-31    2.35    0.60         1
2    M147-50      cat 2018-01-09    4.78    0.80         2
3    K178-56      dog 2018-05-27    7.03    0.75         3
4    T106-20    mouse 2018-09-02    0.75    0.15         1
5    M147-50      cat 2019-03-18    4.78    0.80         2
6    K178-56      dog 2019-03-25    7.03    0.75         3
7    T106-20    mouse 2017-04-01    0.75    0.15         4
8    T156-10      dog 2019-01-04    6.99    0.13         4

处理方法

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"},
    }
}

运行此测试时,出现错误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 。这意味着InMemoryDatabase不具有自动递增功能。

我写错了测试吗?

如何测试这种情况?我要确保命令确定。

可能我在这里错过了一些非常基本的规则。

2 个答案:

答案 0 :(得分:0)

我认为问题在以下几行:

var Context = CBERPContextFactory.Create();

可能您正在将同一上下文实例用于多个测试。根据{{​​3}}文档:

  

每种测试方法都指定一个唯一的数据库名称,这意味着每种方法都有自己的InMemory数据库。

因此请确保您的每个测试方法都具有不同的上下文实例。

如果仍然无法使用,请尝试手动设置身份密钥值,因为InMemory数据库可能不支持自动递增。

答案 1 :(得分:0)

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