Mehfuz's WebLog

Live crazy, think different!

Sponsors

News

Passionate about cutting edge technologies and facinated by the modern web and phone revolution.Currently working at Telerik Corporation, the leading .net component vendor.
Follow me


Articles


Projects

July 2010 - Posts

Mocking LINQ to SQL (Continued…) using OpenAccess

After making the post on mocking LINQ to SQL, this morning i was having a chat with Stephen forte and come to know that Telerik has a new product named Visual Entity Designer that enables you to define your domain model very easily through just few clicks and builds a nice LINQ to SQL model that mimics model similar to Entity framework / MS LINQ to SQL. Being curious, i thought of giving a spin with it and try to mock OpenAccess LINQ to SQL implementation using JustMock.

 

Now, before i start, i also found that OpenAccess has a free / express version that works on top express databases (Ex. SqlExpress) but supports all the features that full version offers. I will be using the free version here. The download is provided at the end of the post along with a link pointing to Steve's introduction of the designer.

 

Once you have downloaded OpenAccess Q2, you first need to create a class library project and inside the add item dialog you need to choose  “Telerik OpenAccess Domain Model” option . Actually, it looks to me same as creating an entity framework edmx just the extension is rlinq.

 image

Next, it will give you an option to choose an empty model or populating it from your database. I would rather choose to populate it from my Northwind database in SqlExpress. That prompts me up with this screen

image

Here to note that i actually first found  the “New Connection” option disabled [may be due to express version] and set my target database using the “Server Explorer” inside visual studio and found it populated as shown above.

Next, i have to choose a model name and by default it suggests “NorthwithEntityDiagram1” but i prefer to choose  “NorthwindDataContext” since things are more with data than with diagram.

image

Once everything is set. I am off to the main topic. I will use the same example from previous post. Accordingly, i created the EmployeeRepository class:

  1. public class EmployeeRepository
  2. {
  3.     public EmployeeRepository(NorthwindDataContext context)
  4.     {
  5.         this.context = context;
  6.     }
  7.  
  8.     public IQueryable<Employee> GetEmployeesByHire(DateTime frm, DateTime to)
  9.     {
  10.         return from emp in context.Employees
  11.                where emp.HireDate >= frm && emp.HireDate <= to
  12.                select emp;
  13.     }
  14.  
  15.     private readonly NorthwindDataContext context;
  16. }

This is plan and simple. There is only method that returns list of employees by hire for a date range. The goal is [those who have missed my previous post] to run the LINQ query into my fake collection to assert the expected behavior of this method.

Therefore, i will be creating a fake data context and for context.Employees i will return my custom collection and finally assert the expected behavior.

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

 

That’s it. As “ReturnsCollection” does a number of tasks on behalf of the developer and which is not required for all cases except for IQueryable / IEnumerable implementations, having few feedbacks from my last post, we have made this as an extension method. The reason is not to pull it up every time for mocking members where you don’t need it.  Therefore, when you need it you just have to include the following line on top your class:

  1. using Telerik.JustMock.Helpers;

The helpers extension[from SP1] also gives an opportunity to add more domain specific methods like “ReturnsCollection” without ever cluttering the core API.

----

You can check the introductory post from Steve of Visual Entity Designer here:

http://www.stephenforte.net/PermaLink,guid,734374ef-65ac-442c-a8f1-571ca9084729.aspx

The free version of OpenAccess ORM can be found here (there are other free and interesting tools as well):

http://www.telerik.com/community/free-products.aspx

OpenAccess version of the sample can be downloaded from: Here

-----

Enjoy!!

Update : RLINQ is not a product on its own rather a extension that Visual entity designer generates [Pardon my ignorance].

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!!!

Posted: Jul 20 2010, 07:28 PM by mehfuzh | with 2 comment(s) |
Filed under: , , ,
More Posts