Unit testing LINQ to SQL

Unit testing LINQ to SQL repositories can be very challenging. Unit testing such requires faking hard to mock classes and requires simulation to return your custom data for a particular LINQ statement. In this post, i will show how you can mock your LINQ repositories easily without much digging in.

As  i was googling [my start page is bing, its a matter of time when i will be bing-ing :-)] around, found a nice post by Ronnie Holm where he shows how to unit test a  LINQ to SQL repository. I will follow his trail and use some of the codes from his post. Therefore, first of all we have an employee class:

  1. public class Employee
  2. {
  3.     public int ID { get; set; }
  4.     public DateTime HireDate { get; set; }
  5. }

Secondly, we have an LINQ DataContext implementation that has the Table<Employee> which we are going to mock with our expected collection.

  1. public partial class AdventureWorksDataContext : DataContext
  2. {
  3.     public AdventureWorksDataContext(string conntection): base(conntection)
  4.     {
  5.         // skip
  6.     }
  7.     public Table<Employee> Employees
  8.     {
  9.         get
  10.         {
  11.             return GetTable<Employee>();
  12.         }
  13.     }
  14. }

Next, we have a repository that contains the LINQ query which is going to be queried on our fake collection that will let us validate the LINQ query in subsequent calls.

  1. public class EmployeeRepository
  2. {
  3.     public EmployeeRepository(AdventureWorksDataContext context)
  4.     {
  5.         this.context = context;
  6.     }
  7.     public IQueryable<Employee> GetEmployeesByHireDate(DateTime start, DateTime end)
  8.     {
  9.         return  from e in context.Employees
  10.              where e.HireDate >= start && e.HireDate <= end
  11.              select e;
  12.     }
  13.     private AdventureWorksDataContext context;
  14. }

Here, i have removed the ToList()  from Ronnie’s code. In ideal case, people may not be having ToList() call into their LINQ query all the time. Secondly, i added the a way to pass our faked DataContext to the repository class. As there should be a minimal dependency to keep the code structure immutable and i think its not a best practice to mock a call for future instance, where it does not have any tie with current code flow.

Finally, its all about mocking , and the steps are:

  1. Create the mock for AdventureWorksDataContext.
  2. Set the context.Employees to return the expected collection.
  3. Finally, act and assert.

Therefore, it becomes:

  1. [TestMethod]
  2. public void ShouldAssertGetEmployeesByHireDate()
  3. {
  4.     var context = Mock.Create<AdventureWorksDataContext>();
  5.     Mock.Arrange(()=> context.Employees).ReturnsCollection(GetFakeEmployees());
  6.     var repository = new EmployeeRepository(context);
  7.     var employees = repository.GetEmployeesByHireDate(new DateTime(2008, 1, 1), DateTime.Now);
  8.     Assert.AreEqual(1, employees.Count());
  9.     Assert.AreEqual(3, employees.FirstOrDefault().ID);
  10. }
  11. private IList<Employee> GetFakeEmployees()
  12. {
  13.     return new List<Employee> {
  14.         new Employee { ID = 1, HireDate = new DateTime(2004, 12, 1) },
  15.         new Employee { ID = 2, HireDate = new DateTime(2006, 7, 1) },
  16.         new Employee { ID = 3, HireDate = new DateTime(2009, 3, 1) } };
  17. }

Here, you might like to ensure that your collection is set right, so it is possible to do

  1. IList<Employee> list = context.Employees.ToList();
  2. Assert.AreEqual(3, list.Count);

That’s it for today. Again special and indirect thanks goes to Ronnie, because i used his code and to him for mentioning JustMock in his post.

Link to the sample project  : LINQToSql001.zip 

Enjoy!!!

No Comments