Bas Bas - 1 month ago 6
C# Question

Best practices for Unit tests using Entity Framework

Edit: I forgot to mention that I'm using a Code First approach

I'm currently developing an application which uses the Entity Framework. The system currently has restaurants (Called Subjects in my code), users and reviews.

I'm brand new to using the Entity Framework, so I was wondering on how I can set up unit tests correctly. I'm assuming I don't have to test any inserting, retrieving and modifying data coming from EF, since this is probably tested already. When I want to set up tests for the code I'm writing, how should I handle objects coming from EF?

I'll give an example of a unit test I have developed. I'm using a repository structure for calls to the database. I'm aware this isn't necessary, but I like the abstraction in case we're switching databases.

My repository looks like this. (The user repository basically follows the same idea)

public class SubjectRepository
{
private readonly RecommenderContext _context;

public SubjectRepository()
{
_context = new RecommenderContext();
}

public Subject FindByGuid(Guid subjectId)
{
return _context.Subjects.Where(x => x.Id == subjectId).FirstOrDefault();
}

public void AddFollower(User userFollowing, Subject subjectToFollow)
{
_context.Subjects.Where(x => x.Id == subjectToFollow.Id).FirstOrDefault().Followers.Add(userFollowing);
_context.SaveChanges();
}

public void CreateSubject(Subject sub)
{
_context.Subjects.Add(sub);
_context.SaveChanges();
}
}


And this is my test class

[TestClass]
public class SubjectRepositoryTests
{
SubjectRepository _subjectRepository;
UserRepository _userRepository;

[TestInitialize]
public void init()
{
_subjectRepository = new SubjectRepository();
_userRepository = new UserRepository();
}

[TestMethod]
public void AddFollower()
{
Subject restaurant = Subject.CreateRandomSubject(); //These functions return randomized objects used for testing
User activeUser = User.CreateRandomUser();

_subjectRepository.CreateSubject(restaurant);
_userRepository.CreateUser(activeUser);

_subjectRepository.AddFollower(activeUser, restaurant);

Assert.AreEqual(activeUser.Id, _subjectRepository.FindByGuid(restaurant.Id).Followers[0].Id);
}
}


Is this a correct way of setting up an unit test? And if so, how would I go around correctly cleaning up the objects I have inserted?

Any other feedback on how to use unit tests in my scenario better would be greatly appreciated!

Answer

Assuming you are using codefirst...

I would avoid having the proper RecommenderContext with direct database calls in it used in the tests. Replace it with an interface inside your repositories, and create a fake implementation that can be injected into your repository for testing. Then you don't have to worry about leaving residue or connecting to the db in tests.

You can use one of the FakeDbSet classes to implement the test context. Effectively this would test your repository logic whilst ignoring the built in EF behaviour, and leave your test nicely isolated.

Comments