Testing with Effort and TypeName attribute

c# dbcontext effort entity-framework unit-testing

Question

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:

  • is there a way that I could use Effort in the tests even if the data model class has attributes
  • if not, what alternative method should I go for to create a fake DbContext?

Accepted Answer

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



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why