I have a method to get an Employer using an Entity Framework context (Lazy Loading is disabled). Sometimes I want the Employees included, sometimes I don't so I have the following code in my data access class:
public Employer GetEmployer(int employerId, bool includeRelationships)
{
Employer employer;
if (includeRelationships)
{
employer = (from e in this.context.Employers.Include(e => e.Employees)
where e.EmployerId == employerId
select e).SingleOrDefault();
}
else
{
employer = this.context.Employers.SingleOrDefault(e => e.EmployerId == employerId);
}
return employer;
}
From several questions about how to use NSubstitute to substitute EF context returns I have this extension method in my test project to hook up the DbSet calls for substitution (specifically NSubstitute DbSet / IQueryable<T>):
public static IDbSet<T> Initialise<T>(this IDbSet<T> dbSet, IQueryable<T> data) where T : class
{
dbSet.Provider.Returns(data.Provider);
dbSet.Expression.Returns(data.Expression);
dbSet.ElementType.Returns(data.ElementType);
dbSet.GetEnumerator().Returns(data.GetEnumerator());
return dbSet;
}
This is then used to initialise a substitute set of Employers in the test class:
[TestInitialize]
public void TestInitialise()
{
this.context = Substitute.For<EmployerContext>();
this.dao = new EmployerDao(this.context);
var employers = new List<Employer>();
var employerWithoutEmployee = new Employer { EmployerId = 1 };
employers.Add(employerWithoutEmployee);
var employerWithEmployee = new Employer { EmployerId = 2 };
var employee = new Employee { EmployeeId = 1, EmployerId = 2, Employer = employerWithEmployee };
employerWithEmployee.Employees.Add(employee);
employers.Add(employerWithEmployee);
this.substituteEmployers = Substitute.For<IDbSet<Employer>>().Initialise(employers.AsQueryable());
this.context.Employers.Returns(this.substituteEmployers);
}
So, I now have a test that looks like this:
[TestMethod]
public void ReturnsEmployerWithNullEmployeeWhenIncludeIsFalse()
{
// Assemble
var expectedEmployer = this.substituteEmployers.First(e => e.Employees.Any();
var employerId = expectedEmployer.EmployerId;
// Act
var actualEmployer = this.dao.GetEmployer(employerId, false);
var actualEmployee = actualEmployer.Employees.FirstOrDefault();
// Assert
Assert.AreSame(expectedEmployer, actualEmployer);
Assert.IsNotNull(actualEmployer);
Assert.IsNull(actualEmployee);
this.context.Employers.ReceivedWithAnyArgs();
}
This test is failing on Assert.IsNull(actualEmployee);
In real usage, GetEmployer will return an Employer with no Employee children.
However, because I am substituting an Employer with Employee (because this is what I am testing!) the method is returning the substitute which has an Employee.
How can I test this?
Or, am I testing incorrectly?
Should I instead use the Employer which doesn't have an Employee, because that is what the context would return?
But then doesn't that make the test pointless!?!
I'm thinking myself in circles here...
[TestInitialize]method:this.context.Configuration.LazyLoadingEnabled = false;- George Howarthemployer = this.context.Employers.SingleOrDefault(e => e.EmployerId == employerId);line in the dao method. its passing the substitute straight through - ShevekemployerWithEmployee.Employees.Add(employee);that's messing it up. By doing that, it's settingEmployeesto a non-null value and thus mimicking the behavior of a context which has already lazily loaded that collection. Sorry, kind of clutching at straws here... - George Howarth