使用 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

总而言之,我的问题是:

我建议您查看 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; }
}