私はいくつかのコードをテストしたいと思います。これを達成するために、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
スローされ、
シーケンスに一致する要素が含まれていません
それを要約すると、私の質問は:
私はEntityTypeConfigurationsを見てそこにあなたのマッピングを移動することをお勧めします: http : //www.entityframeworktutorial.net/code-first/entitytypeconfiguration-class.aspx
これにより、使用している現在のDBを考慮せず、Entity Frameworkを考慮せずにエンティティ/インターフェイスを使用してエンティティ/インターフェイスをテストすることができます。
また、ユニットテストの代わりに統合テストを行っていることもわかります。ユニットテストを行うには、実際のDbContextの使用を取り除く必要があります(現在の実装では、DAL用の具体的なEF実装を使用していますが、代わりにいくつかの抽象化を使用する必要があります)。
私は少なくともあなたのDbContextをインタフェースでラップして、それをモックすることができる/より良い方法でスタブすることを推奨します:
public interface IDbContext {
IDbSet<Customer> Customers { get; set; }
}