努力支持的单元测试冲突

Effort supported unit tests conflict

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

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

我是否 运行 并行测试并不重要。

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

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

看来测试没有正确隔离。
跟踪代码,我可以看到调用了 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);

这是非常复杂的代码,所以如果我们需要 post 更多代码,我们需要很长时间才能找到兔子洞的底部。创建一个 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) { }

'Find' 现在可以工作了,测试不会相互干扰。
下一步是将这一切推到基础 类.