I'd like to test some code, and to achieve that, I'd need to fake DbContext defined in DAL (Entity Framework 6 - Code first
). It's going mostly well, but I bumped into an problem when the data model class is using the TypeName
attribute. I made a skeleton to demonstrate the issue.
The data model:
[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; }
}
The context definition
public class MyDbContext : DbContext
{
public MyDbContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public MyDbContext(DbConnection connection) : base(connection, true)
{
}
public IDbSet<Customer> Customers { get; set; }
}
And a dummy method to generate a fake context with some data:
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;
}
The problem is the TypeName
attribute. When it's commented out, tests pass. But if it's enabled, I got a System.InvalidOperationException
thrown, saying
Sequence contains no matching element
To sum it up, my questions are:
I would advise you to take a look at EntityTypeConfigurations and move your mappings there: http://www.entityframeworktutorial.net/code-first/entitytypeconfiguration-class.aspx
It will allow you not to take into account your current DB used and test your entities/interfaces using them without taking Entity Framework into account.
It also looks to me, that you are doing integration testing instead of unit-testing. To do unit-testing, you should get rid of real DbContext usage (your current implementation is using concrete EF implementation for DAL, but should use some abstraction instead.)
I would recommend to at least wrap your DbContext in an interface so that you could mock it/stub it in a better way:
public interface IDbContext {
IDbSet<Customer> Customers { get; set; }
}