努力支持单元测试冲突

c# effort entity-framework-6 unit-testing vstest

我继承了这个项目的一些测试。他们在对SQL数据库运行时工作,但速度很慢。我正在尝试切换到使用Effort。
.NET4.5,EF6.2,Effort 1.3.10。

我的单元测试有两个可能相关的问题。

如果我并行运行测试并不重要。

1)如果我一次运行多个,我得到

保存或接受更改失败,因为“Center.Shared.Person”类型的多个实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和Entity Framework模型中正确配置了数据库生成的主键。使用实体设计器进行数据库优先/模型优先配置。使用'HasDatabaseGeneratedOption'流畅API或'DatabaseGeneratedAttribute'进行代码优先配置.---> System.InvalidOperationException:保存或接受更改失败,因为多个类型为'Center.Shared.Person'的实体具有相同的主键值。确保显式设置主键值是唯一的。确保在数据库和Entity Framework模型中正确配置了数据库生成的主键。使用实体设计器进行数据库优先/模型优先配置。使用'HasDatabaseGeneratedOption'流畅API或用于Code First配置的'DatabaseGeneratedAttribute'..

所以似乎测试没有被正确隔离。
通过代码跟踪,我可以看到CreateTransient被调用,但它显然不够短暂。

    public DbConnection CreateConnection(string nameOrConnectionString)
    {
        lock (_lock)
        {
            if (_connection == null)
            {
                _connection = Effort.DbConnectionFactory.CreateTransient();
            }

            return _connection;
        }
    }

在TestInitialize例程中,我尝试重置数据库。

    [TestInitialize]
    public override void Initialize()
    {
        db.Database.Delete();
        db.Database.CreateIfNotExists();
        db.Database.Initialize(true);

这是一个高度复杂的代码,所以如果我们需要发布更多的代码,那么我们需要很长时间才能找到兔子洞的底部。可能更好地创建PoC。

2)如果我独立运行测试,我会遇到不同的问题。同样,这些是针对SQL而不是Effort传递的。

    [TestMethod]
    public void ClientAccessorTests_Find()
    {
        Client result;
        Client client = new Client()
        {
            Complete = false,
            HeadOfHousehold = true,
            PersonID = _person.PersonID
        };

        _accessor.Create(client, _accessor.DefaultConnectionContext);

        result = _accessor.Find(new object[] { client.ClientID }, _accessor.DefaultConnectionContext);

        Assert.IsNotNull(result);  // Fails with Assert.IsNotNull failed. 
    }

创建包括

    public virtual EntityType Create(EntityType entity, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (entity == null) throw new ArgumentException("", "entity");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            db.Set<EntityType>().Add(entity);
            db.SaveChanges();
        }

        return entity;
    }

查找包括

    public virtual EntityType Find(object[] primaryKey, ConnectionContext connectionContext)
    {
        IsContextValid(connectionContext);
        if (primaryKey == null || primaryKey.Length == 0) throw new ArgumentException("", "primaryKey");

        using (var db = CreateDbContext<DbContextType>(connectionContext))
        {
            return db.Set<EntityType>().Find(primaryKey);
        }
    }

我知道它正在调用CreateDbContext,但是跟踪代码,据我所知,它似乎是具有相同ID的相同数据库。

是什么导致测试被隔离?
关于为什么在使用内存数据库时Find会退出工作的任何想法?

一般承认的答案

我试图使用隐式方法,其中所有内容都通过app.config文件中的设置连接起来。
一旦我放弃了这种方法并创建了数据库连接并明确地设置它,我就开始有了更好的运气。

        System.Data.Common.DbConnection connection = new EffortProviderFactory("").CreateConnection("");
        _accessor = new ClientAccessor();
        _accessor.Connection = connection;
        db = new EntitiesDb(connection);

基本访问器每次都会创建数据库的副本,只要它使用相同的DbConnection就可以了。所以我在访问器上设置它然后在这里使用它:

        if (_connection == null) {   // this is the path for the application
            if (connectionContext == null) {
                ret = new T();
            } else {
                ret = (T)Activator.CreateInstance(typeof(T), new object[] { connectionContext });
            }
        } else {  // this is the path for unit tests.
            ret = (T)Activator.CreateInstance(typeof(T), new object[] { _connection });
        }

最后,我必须添加一个构造函数,它将DbConnection带到DbContext及其后代。

    public EntitiesDb(DbConnection connection) : base(connection) { }

“查找”现在有效,测试不会相互干扰。
下一步是将这一切推向基类。




许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因