我繼承了這個項目的一些測試。他們在對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) { }
“查找”現在有效,測試不會相互干擾。
下一步是將這一切推向基類。