使用Effort和TypeName属性进行测试

时间:2015-12-13 20:05:06

标签: c# entity-framework unit-testing dbcontext effort

我想测试一些代码,为了实现这一点,我需要伪造在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,说

  

序列不包含匹配元素

总结一下,我的问题是:

  • 有一种方法可以在测试中使用Effort,即使数据模型类具有属性
  • 如果没有,我应该采用哪种替代方法来创建假DbContext?

1 个答案:

答案 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; }
}