How do you mock adding items to a repository or DbContext using moq?

前端 未结 5 1129
猫巷女王i
猫巷女王i 2021-01-23 17:00

The examples I\'ve seen for using moq for a repository only show how to mock things being returned. I have a somewhat strange requirement: when a query is executed, if a conditi

相关标签:
5条回答
  • 2021-01-23 17:12

    This blog article might be of use, although my design has changed somewhat since I wrote the post and I really need to update it. I used teh generic repository pattern in a way that enables the DbContext to be mocked. This allows the data access layer to be tested 'right up to the edges'. Generic Repository and Unit of Work

    0 讨论(0)
  • 2021-01-23 17:25

    You would not mock the repository; you would have an alternate repository that would use an in-memory store instead of the database, then use IoC to select the correct repository implementation for tests/code.

    0 讨论(0)
  • 2021-01-23 17:27

    Try to use fake in memory repository instead of moq, for example universal generic repository for all entities:

    public interface IInMemoryRepository<T> where T : class
    {
        IQueryable<T> GetAll();
        void Create(T item);
        void Update(T item);
        T GetItem(Expression<Func<T, bool>> expression);
        void Delete(T item);
    }
    
    public class InMemoryRepository<T> : IInMemoryRepository<T> where T : class
    {
        private int _incrementer = 0;
        public Dictionary<int, T> List = new Dictionary<int, T>();
    
        public IQueryable<T> GetAll()
        {
            return List.Select(x => x.Value).AsQueryable();
        }
    
        public void Create(T item)
        {
            _incrementer++;
            item.GetType().GetProperties().First(p => p.Name == "Id").SetValue(item, _incrementer, null);
            List.Add(_incrementer, item);
        }
    
        public void Update(T item)
        {
            var key = (int)item.GetType().GetProperties().First(p => p.Name == "Id").GetValue(item, null);
            List[key] = item;
        }
    
        public T GetItem(Expression<Func<T, bool>> expression)
        {
            return List.Select(x => x.Value).SingleOrDefault(expression.Compile());
        }
    
        public void Delete(T item)
        {
            var key = (int)item.GetType().GetProperties().First(p => p.Name == "Id").GetValue(item, null);
            List.Remove(key);
        }
    }
    
    0 讨论(0)
  • 2021-01-23 17:27

    Times have changed -- since the release of Entity Framework 6 it has become much easier to mock database context and datasets. This article outlines the particulars.

    Testing non-query scenarios

    using Microsoft.VisualStudio.TestTools.UnitTesting; 
    using Moq; 
    using System.Data.Entity; 
    
    namespace TestingDemo 
    { 
        [TestClass] 
        public class NonQueryTests 
        { 
            [TestMethod] 
            public void CreateBlog_saves_a_blog_via_context() 
            { 
                var mockSet = new Mock<DbSet<Blog>>(); 
    
                var mockContext = new Mock<BloggingContext>(); 
                mockContext.Setup(m => m.Blogs).Returns(mockSet.Object); 
    
                var service = new BlogService(mockContext.Object); 
                service.AddBlog("ADO.NET Blog", "http://blogs.msdn.com/adonet"); 
    
                mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once()); 
                mockContext.Verify(m => m.SaveChanges(), Times.Once()); 
            } 
        } 
    }
    

    Testing query scenarios Query testing is pretty sweet now, because you can build up test data sets in code and then execute your tests against them:

    using Microsoft.VisualStudio.TestTools.UnitTesting; 
    using Moq; 
    using System.Collections.Generic; 
    using System.Data.Entity; 
    using System.Linq; 
    
    namespace TestingDemo 
    { 
        [TestClass] 
        public class QueryTests 
        { 
            [TestMethod] 
            public void GetAllBlogs_orders_by_name() 
            { 
                var data = new List<Blog> 
                { 
                    new Blog { Name = "BBB" }, 
                    new Blog { Name = "ZZZ" }, 
                    new Blog { Name = "AAA" }, 
                }.AsQueryable(); 
    
                var mockSet = new Mock<DbSet<Blog>>(); 
                mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider); 
                mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression); 
                mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType); 
                mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(0 => data.GetEnumerator()); 
    
                var mockContext = new Mock<BloggingContext>(); 
                mockContext.Setup(c => c.Blogs).Returns(mockSet.Object); 
    
                var service = new BlogService(mockContext.Object); 
                var blogs = service.GetAllBlogs(); 
    
                Assert.AreEqual(3, blogs.Count); 
                Assert.AreEqual("AAA", blogs[0].Name); 
                Assert.AreEqual("BBB", blogs[1].Name); 
                Assert.AreEqual("ZZZ", blogs[2].Name); 
            } 
        } 
    }
    
    0 讨论(0)
  • 2021-01-23 17:33

    You can do this by mocking the DbSet.Add() method, like so:

    [Fact]
    public void CreateBlog_saves_a_blog_via_context()
    {
      var data = new List<Blog>
      {
        new Blog { Name = "BBB" },
        new Blog { Name = "ZZZ" },
        new Blog { Name = "AAA" },
      };
      
      var mockSet = new Mock<DbSet<Blog>>();
      mockSet.Setup(blogs => blogs.Add(It.IsAny<Blog>)).Returns<Blog>(blog =>
      {
        data.Add(blog);
        return blog;
      });
      
      var mockContext = new Mock<BloggingContext>();
      mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
      
      var service = new BlogService(mockContext.Object);
      var blog = service.AddBlog("_ADO.NET Blog", "http://blogs.msdn.com/adonet");
      var blogs = service.GetAllBlogs();
      
      mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
      mockContext.Verify(m => m.SaveChanges(), Times.Once());
      
      Assert.NotNull(blog)
      Assert.Equal(4, blogs.Count);
      Assert.Equal("AAA", blogs(1).Name);
      Assert.Equal("BBB", blogs(2).Name);
      Assert.Equal("ZZZ", blogs(3).Name);
    }
    

    This is adapted from the documentation found here.

    0 讨论(0)
提交回复
热议问题