I have an application that contains methods that work with data using Entity Framework 4.2 Code First and a MySQL database. I am trying to figure out a good way to write an MSTest unit test for these methods. For example:
DataModel:
public class User
{
public User() { }
[Key]
public int UserID { get; set; }
public string Role { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<User> Users { get; set; }
}
Business Layer:
public class Bus
{
public bool UserIsInRole(int userID, string role)
{
using(var context = new AppDbContext())
{
User user = context.Users.SingleOrDefault(p => p.UserID == userID);
if (user == null)
return false;
return user.Roles.Split(',').Contains(role);
}
}
}
I am trying to write a set of unit tests for the UserIsInRole function, but I want to try to isolate myself from actually having to read and write to the actual database since I cannot guarantee its state before the test. Setting up/tearing down a database just for this test would take too long.
I have ran into many articles about using fake DbContext, such as here, here, and here but they all seem to have some pros and cons. One group of people say that one should not write unit tests against EF and that this belongs to integration testing and that any fake DbContext don't behave enough like the real thing for the purpose of acceptable tests.
I think code like this lies someplace in the middle of the argument. Ideally, I want to create a set of temporary, in-memory objects that represent the desired data without having to actually store it into the database.
How would you change the above and write a set of tests that verify that the UserIsInRole method:
- returns false if the userID does not exist in the Users collection.
- returns false if the user does not contain the desired role.
- returns true if the user has the desired role.
Keep in mind that this is a simplified example and that code could actually contain multiple queries of arbitrary complexity so I am hoping to find something a bit more comprehensive than, say, moving every query to a virtual function that is replaced by the test framework to return a predefined User record.