努力支持單元測試衝突

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) { }

“查找”現在有效,測試不會相互干擾。
下一步是將這一切推向基類。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因