Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting up mock objects for EF dbcontext to test repository methods

I have entityframework repo which gets trip information from sqldb. I have created the repo and on constructor injecting the dbContext and using that context doing database operation.

 public class WorldRepository : IWorldRepository
    {
        private WorldContext _context;

        public WorldRepository(WorldContext context)
        {
            _context = context;
        }

        public void AddSop(string tripName, Stop newStop)
        {
            var trip = GetTipByName(tripName);

            if (trip != null)
            {
                trip.Stops.Add(newStop);
                _context.Stops.Add(newStop);
            }
        }

        public void AddTrip(Trip trip)
        {
            _context.Add(trip);
        }

        public IEnumerable<Trip> GetAllTrips()
        {
            return _context.Trips.ToList();
        }
}

Now I am trying to test using MOQ, but this does not help . I am not able to test any of logic writen on my methods as it's querying mock object and not my implementation.

  // private Mock<IWorldRepository> _mockWorld;

        [TestMethod]
        public void Test_AddTrips()
        {
            //Arrange
            // WorldRepository repo = new WorldRepository(null);

            Mock<IWorldRepository> _mockWorld = new Mock<IWorldRepository>();
            var repo = _mockWorld.Object;

            //Act
            repo.AddSop("Sydney", new Stop
            {
                Arrival = DateTime.Now,
                Id = 2,
                Latittude = 0.01,
                Longitude = 0.005,
                Name = "Test Trip",
                Order = 5
            });

            repo.SaveChangesAsync();

            var count = repo.GetAllTrips().Count();

            //Assert
            Assert.AreEqual(1, count);


        }

This is code for WorldContext.

public class WorldContext:DbContext
    {
        private IConfigurationRoot _config;

        public WorldContext(IConfigurationRoot config,DbContextOptions options)
            :base(options)
        {
            _config = config;
        }

        public DbSet<Trip> Trips { get; set; }
        public DbSet<Stop> Stops{ get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer(_config["ConnectionStrings:WorldCotextConnection"]);
        }
    }
like image 840
ZonesMiller Avatar asked Mar 07 '23 18:03

ZonesMiller


1 Answers

I am assuming that you are trying to mock WorldContextand to use it with your repo instance ,so we need to mock that first. To do that create an interface for worlddbcontext.

public interface IWorldContext
    {
        DbSet<Stop> Stops { get; set; }
        DbSet<Trip> Trips { get; set; }
    }

Now what you want is to mock the dependencies and the test the subject.

In this case you want to mock WorldDbContext , mock the DbSet<Stop> and test AddSop method.

To create a mock DbSet, I am refering to MSDN, EF Testing with Mocking framework as also mentioned by Jasen in the comments.

 private Mock<IWorldContext> _context;
 private WorldRepository _repo;

        [TestMethod]
        public void Test_AddTrips()
        {
            ////Arrange          

            var data = new List<Stop> {
                 new Stop
                {
                    Arrival = DateTime.Now.AddDays(-15),
                    Id = 1,
                    Latittude = 0.05,
                    Longitude = 0.004,
                    Name = "Test Trip01",
                    Order = 1
                },
                   new Stop
                {
                    Arrival = DateTime.Now.AddDays(-20),
                    Id = 2,
                    Latittude = 0.07,
                    Longitude = 0.015,
                    Name = "Test Trip02",
                    Order = 2
                }

            }.AsQueryable();

            var mockSet = new Mock<DbSet<Stop>>();
            mockSet.As<IQueryable<Stop>>().Setup(m => m.Provider).Returns(data.Provider);
            mockSet.As<IQueryable<Stop>>().Setup(m => m.Expression).Returns(data.Expression);
            mockSet.As<IQueryable<Stop>>().Setup(m => m.ElementType).Returns(data.ElementType);
            mockSet.As<IQueryable<Stop>>().Setup(m => m.GetEnumerator()).Returns( data.GetEnumerator());


            _context = new Mock<IWorldContext>();

           //Set the context of mock object to  the data we created.
            _context.Setup(c => c.Stops).Returns(mockSet.Object);

           //Create instance of WorldRepository by injecting mock DbContext we created
            _repo = new WorldRepository(_context.Object);    


            //Act
            _repo.AddSop("Sydney",
                new Stop
                {
                    Arrival = DateTime.Now,
                    Id = 2,
                    Latittude = 0.01,
                    Longitude = 0.005,
                    Name = "Test Trip",
                    Order = 5
                });

            _repo.SaveChangesAsync();

            var count = _repo.GetAllTrips().Count();

            //Assert
            Assert.AreEqual(3, count);


        }

Also , there is a brilliant module (just a reference, no endorsement or anything else) on plural sight by Mosh on Testing Repository module he has explained this in great detail.

like image 187
Simsons Avatar answered May 07 '23 06:05

Simsons