I'am testing my Entity Framework repository but I got some problems when using Moq - Unit Test specially when test a method with related objects.
The problem occurs when I try sending mock object [Patient] with some [Bookings] as the data source of a repository method and query it to get a patient with conditional bookings but I'm getting all the bookings even not satisfy the conditions. My tests working perfectly when querying directed objects with no conditional related ones.
Test SetUp Method
[SetUp]
public void Setup()
{
var mockDbContext = new Mock<IApplicationDbContext>();
mockPatient = new Mock<DbSet<Patient>>();
mockBookings = new Mock<DbSet<Booking>>();
var patient = new Patient()
{
Id = 1,
Name = "Amin",
Bookings = GetBookings()
};
var bookings = GetBookings();
mockPatient.SetSource(new List<Patient>() { patient });
mockBookings.SetSource(bookings);
mockDbContext.SetupGet(c =>
c.Patients).Returns(mockPatient.Object);
mockDbContext.SetupGet(c =>
c.Bookings).Returns(mockBookings.Object);
_repository = new PatientRepository(mockDbContext.Object);
}
private static List<Booking> GetBookings()
{
return new List<Booking>() {
new Booking() {
Patient_Id=1,
DateTime = DateTime.Now.AddDays(3) ,
State = new BookingState() {Id=1, Name="Active"}
},
new Booking() {
Patient_Id=1,
DateTime = DateTime.Now.AddDays(4) ,
State = new BookingState() {Id=2, Name="Pending" }
}
};
}
Tested Method :
[Test]
public void GetPatientsWithBookings_GetActiveBookings_ReturnBookings()
{
var patients = _repository.GetPatientsWithBookings("Active");
Assert.That(patients[0].Bookings.Count, Is.EqualTo(1));
}
Method Implementation :
public IList<Patient> GetPatientsWithBookings( string state)
{
var Patients = _context.Patients.ToList();
var PatientsIDs = Patients.Select(p => p.Id);
_context.Bookings.Where(p => PatientsIDs.Contains(p.Patient_Id) && p.State.Name.Equals(state)).Load();
return Patients;
}
SetSource Method :
public static void SetSource<T>(this Mock<DbSet<T>> mockSet, IList<T> source) where T : class
{
var data = source.AsQueryable();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => data.GetEnumerator());
mockSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => source.Add(s));
}
Expected : return only one booking which is "Active".
Output : return whole bookings types.