0

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.

Amin Mohamed
  • 640
  • 7
  • 10
  • I wonder ! is no one able to help !! – Amin Mohamed Sep 08 '19 at 23:10
  • 1
    that's not something you should be doing. if you want to test your database layer then either use integration testing, as in use your real database or use an in-memory one. either way, you're working with an actual database. don't try to mock Entity Framework, you'll waste your time for nothing – Andrei Dragotoniu Sep 09 '19 at 10:10

0 Answers0