努力支持的单元测试冲突
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' 现在可以工作了,测试不会相互干扰。
下一步是将这一切推到基础 类.
我继承了这个项目的一些测试。他们在 运行 对 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' 现在可以工作了,测试不会相互干扰。
下一步是将这一切推到基础 类.