受支持的单元测试冲突

时间:2018-11-02 07:48:11

标签: c# unit-testing entity-framework-6 vstest effort

我已经对该项目继承了一些测试。在针对SQL数据库运行时,它们正在工作,但速度很慢。我正在尝试改用Effort。
.NET4.5,EF6.2,努力1.3.10。

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

是否并行运行测试都没关系。

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

保存或接受更改失败,因为多个“ Center.Shared.Person”类型的实体具有相同的主键值。确保显式设置的主键值是唯一的。确保在数据库和实体框架模型中正确配置了数据库生成的主键。将实体设计器用于数据库优先/模型优先配置。为代码优先配置使用“ HasDatabaseGeneratedOption”流利的API或“ DatabaseGeneratedAttribute” ---> System.InvalidOperationException:由于多个“ Center.Shared.Person”类型的实体具有相同的主键值,因此保存或接受更改失败。确保显式设置的主键值是唯一的;确保在数据库和Entity Framework模型中正确配置了数据库生成的主键;使用实体设计器进行数据库优先/模型优先配置;使用'HasDatabaseGeneratedOption“流利API或用于代码优先配置的'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,但没有通过。

    [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的相同数据库。

应该导致隔离测试的原因是什么?
以及关于使用内存数据库时查找为什么会退出工作的任何想法?

1 个答案:

答案 0 :(得分:0)

我尝试使用隐式方法,其中所有内容都通过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) { }

“查找”现在可以使用,并且测试不会相互干扰。
下一步是将所有这些推入基类。