Question

I am using Entity Framework 4.1 for database access and would like to Unit Test the following code:

// Get all the entities including children
using (MyContext context = new MyContext())
{
    return context.EmployeeProfiles.Include("EmployeeProperties").ToList();
}

I am using Moles to mole out the database dependency however I am stuck. Which point in the Entity Framework I should begin to mole out.

I was following this example but it is for LINQ-To-SQL.

I was also thinking of debugging/tracing the Entity Framework to figure out which function to intercept out before the call to the database is made. However, it seems that there is no source code available for Entity Framework 4.1 to trace with. See discussion.

Can anyone guide me to which function(s) I should be moling out in the DbContext so I can get a list of EmployeeProfiles back?

Was it helpful?

Solution

It looks to me like rather than removing the dependency on EF via a Repository pattern, you're trying to mock the specific behaviour of EF. I can't see the point in trying to do that and it would be very difficult, EF isn't meant to be mocked.

Your repository is presumably something like this:

public interface IRepository
{
      IEnumerable<EmployeeProfiles> EmployeeProfiles { get; }
}

public class Repository
{
    public IEnumerable<EmployeeProfiles> EmployeeProfiles
    {
        get
        {
            // Get all the entities including children     
            using (MyContext context = new MyContext())     
            {
                return context.EmployeeProfiles.Include("EmployeeProperties").ToList();     
            }
        }
    }
}

This way you have removed the repository dependency on how the EmployeeProfiles is returned. Now you can mock-away to your heart's content (haven't yet used Moles), but with Moq, you would do something like:

public void TestEmptyList()
{
    var mock = new Mock<IRepository>();
    var expected = new List<EmployeeProfiles>();
    mock.SetupGet(ep => ep.EmployeeProfiles).Returns(expected);

    var actual = mock.Object.EmployeeProfiles;

    Assert.AreEqual(expected, actual);
}

So, if you put the methods/properties you want to abstract away from the database into the repository interface, then you can mock out any values you want to test that it might return.

Maybe you're doing this anyway, I'm not sure. I don't see why you'd want to unit test EF, what would you hope to gain? It would be immensely hard, it's not designed to be mocked (very few interfaces/ virtuals). Any mocking of data you return, which is really all you are really interesting in would be done as above.

OTHER TIPS

This is totally possible, and in my opinion, valid. Yes, you can use a repository pattern and mock your repository, and often that is good enough.

However, two arguments I've seen for mocking EF:

  1. EF is already an abstraction/repository over the actual database, writing another repository around it isn't necessary.
  2. Any repository you write over EF is your code. Therefore, you should test it, as sooner or later you're going to end up adding logic that needs to be covered.

This is a bit of a holy war at this point, but there are arguments out there that support what you are doing.

So, to do this with Moles, you'll need to do two things. First, change the template that creates your DbContext so that the return types of all your tables are IDbSet<> instead of DbSet<>.

Then, in your test project, add a test class implementation for IDbSet. I've found this one to work well.

Now, in your test, you can do the following:

List<EmployeeProfile> testProfiles = /*your test data here*/;
MMyContext.AllInstances.EmployeeProfilesGet  = (instance) => 
{
    return new InMemoryDbSet<EmployeeProfile>(testProfiles);
};


// Get all the entities including children
using (MyContext context = new MyContext())
{
    return context.EmployeeProfiles.Include("EmployeeProperties").ToList();
}

It's quick, simple, and allows you to test your code right up to the very point it leaves your control.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top