我想测试一些代码,为了实现这一点,我需要伪造在DAL(Entity Framework 6 - Code first
)中定义的DbContext。它的效果非常好,但是当数据模型类使用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
,说
序列不包含匹配元素
总结一下,我的问题是:
答案 0 :(得分:0)
我建议你看看EntityTypeConfigurations并在那里移动你的映射: http://www.entityframeworktutorial.net/code-first/entitytypeconfiguration-class.aspx
它允许您不考虑当前使用的数据库并使用它们测试您的实体/接口,而不考虑实体框架。
在我看来,您正在进行集成测试而不是单元测试。要进行单元测试,你应该摆脱真正的DbContext使用(你当前的实现是使用DAL的具体EF实现,但应该使用一些抽象。)
我建议至少将DbContext包装在一个界面中,这样你就可以用更好的方式模拟它/ stub:
public interface IDbContext {
IDbSet<Customer> Customers { get; set; }
}