使用 Effort 和 TypeName 属性进行测试
Testing with Effort and TypeName attribute
我想测试一些代码,为此,我需要伪造 DAL 中定义的 DbContext (Entity Framework 6 - Code first
)。大部分情况下进展顺利,但当数据模型 class 使用 TypeName
属性时我遇到了问题。我做了一个骨架来演示这个问题。
数据模型:
[Table("Customer")]
public class Customer
{
[Key]
public int Id { get; set; }
public string FirstName{ get; set; }
public string LastName { get; set; }
//this line causes the exception
[Column(TypeName = "money")]
public decimal Salary { get; set; }
}
上下文定义
public class MyDbContext : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public MyDbContext(DbConnection connection) : base(connection, true)
{
}
public IDbSet<Customer> Customers { get; set; }
}
以及使用一些数据生成假上下文的虚拟方法:
private MyDbContext GenerateFakeDbContext()
{
var connection = DbConnectionFactory.CreateTransient();
var context = new MyDbContext(connection);
var customer = new Customer
{
Id = 1,
FirstName = "X",
LastName = "Y",
Salary = 1000
};
//this line throws the exception
context.Customers.Add(customer);
return context;
}
问题是 TypeName
属性。当它被注释掉时,测试通过。但是如果它被启用,我得到一个 System.InvalidOperationException
抛出,说
Sequence contains no matching element
总而言之,我的问题是:
- 有没有一种方法可以在测试中使用 Effort,即使数据模型 class 具有属性
- 如果不是,我应该使用什么替代方法来创建伪造的 DbContext?
我建议您查看 EntityTypeConfigurations 并将您的映射移动到那里:
http://www.entityframeworktutorial.net/code-first/entitytypeconfiguration-class.aspx
它将允许您不考虑您当前使用的数据库并使用它们测试您的entities/interfaces而不考虑Entity Framework。
在我看来,您正在进行集成测试而不是单元测试。要进行单元测试,您应该摆脱真正的 DbContext 使用(您当前的实现是使用 DAL 的具体 EF 实现,但应该改用一些抽象。)
我建议至少将您的 DbContext 包装在一个界面中,以便您可以更好地模拟 it/stub 它:
public interface IDbContext {
IDbSet<Customer> Customers { get; set; }
}
我想测试一些代码,为此,我需要伪造 DAL 中定义的 DbContext (Entity Framework 6 - Code first
)。大部分情况下进展顺利,但当数据模型 class 使用 TypeName
属性时我遇到了问题。我做了一个骨架来演示这个问题。
数据模型:
[Table("Customer")]
public class Customer
{
[Key]
public int Id { get; set; }
public string FirstName{ get; set; }
public string LastName { get; set; }
//this line causes the exception
[Column(TypeName = "money")]
public decimal Salary { get; set; }
}
上下文定义
public class MyDbContext : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public MyDbContext(DbConnection connection) : base(connection, true)
{
}
public IDbSet<Customer> Customers { get; set; }
}
以及使用一些数据生成假上下文的虚拟方法:
private MyDbContext GenerateFakeDbContext()
{
var connection = DbConnectionFactory.CreateTransient();
var context = new MyDbContext(connection);
var customer = new Customer
{
Id = 1,
FirstName = "X",
LastName = "Y",
Salary = 1000
};
//this line throws the exception
context.Customers.Add(customer);
return context;
}
问题是 TypeName
属性。当它被注释掉时,测试通过。但是如果它被启用,我得到一个 System.InvalidOperationException
抛出,说
Sequence contains no matching element
总而言之,我的问题是:
- 有没有一种方法可以在测试中使用 Effort,即使数据模型 class 具有属性
- 如果不是,我应该使用什么替代方法来创建伪造的 DbContext?
我建议您查看 EntityTypeConfigurations 并将您的映射移动到那里: http://www.entityframeworktutorial.net/code-first/entitytypeconfiguration-class.aspx
它将允许您不考虑您当前使用的数据库并使用它们测试您的entities/interfaces而不考虑Entity Framework。
在我看来,您正在进行集成测试而不是单元测试。要进行单元测试,您应该摆脱真正的 DbContext 使用(您当前的实现是使用 DAL 的具体 EF 实现,但应该改用一些抽象。)
我建议至少将您的 DbContext 包装在一个界面中,以便您可以更好地模拟 it/stub 它:
public interface IDbContext {
IDbSet<Customer> Customers { get; set; }
}