unit-testingentity-framework-4typemock-isolator

How to Include associated entities


I want to create test case for below method "GetByEmail".

 public User GetByEmail(string email, bool includeUserRoles = false, bool includeUserType = false)
 { 
    Expression<Func<User>> whereClause = u => u.Email == email; 

    return GetQuery(whereClause, includeUserRoles, includeUserType) .FirstOrDefault(); 
 } 

 private IQueryable<User> GetQuery(Expression<Func<User>> whereClause, 
                                   bool includeUserRoles = false, bool includeUserType = false) 
 { 
   IQueryable<User> query = base.GetQuery(whereClause); 

   if (includeUserRoles) 
     query = query.Include(u => u.UserRoles); 

   if (includeUserType) 
     query = query.Include(u => u.UserType); 

   return query; 
 } 

 protected IQueryable<T> GetQuery<T>(Expression<Func<T>> predicate) where T : EntityBase
 { 
    return predicate != null ? 
             CreateObjectSet<T>().Where(predicate) : 
             CreateObjectSet<T>(); 
 } 

 protected IObjectSet<T> CreateObjectSet<T>() where T : EntityBase 
 { 
   return _context.CreateObjectSet<T>(); 
 } 

 public static IQueryable<T> Include<T>(this IQueryable<T> source, Expression<Func<T>> property)
 { 
   var objectQuery = source as ObjectQuery<T>; 

   if (objectQuery != null) 
   { 
      var propertyPath = GetPropertyPath(property); 
      return objectQuery.Include(propertyPath); 
   } 

   return source; 
 } 

Below is my test case method -

[Fact] 
private void GetByEmail_PassedEmailAddress_RelatedUser() 
{ 
  //Created fake context 
  var fakeContext = Isolate.Fake.Instance<Entities>(); 

  //Created fake Repository and passed fakeContext to it 
  var fakeRepository = Isolate.Fake.Instance<Repository>(Members.CallOriginal,   ConstructorWillBe.Called, fakeContext);

  //Created fake in memory collection of User 
  var fakeUsers = GetUsers(); 

  Isolate.WhenCalled(() => fakeContext.Context.CreateObjectSet<User>()) 
         .WillReturnCollectionValuesOf(fakeUsers); 

  var User = Isolate.Invoke.Method(fakeRepository, "GetByEmail", "abc@xyz.com", true, true);

  Assert.True(User != null); 
} 

In the above test case method I successfully get the user with passed email but not able to include other entities of associated user.

Kindly let me know, how can I include other entities with associated User.


Solution

  • Include is leaky abstraction - it works only with EF and linq-to-entities and cannot be successfully used with linq-to-objects. You know that your unit test needs populated relations so your GetUsers method must prepare that data. That is a point of mocking / faking - you don't think about internal implementation of mocked method. You simply return what should be returned.

    Btw. what is the point of your test? It looks like you are trying to test a mock - that is wrong. Mock provides correct data and you only need it to test another feature dependent on mocked component.