我看到的将 moq 用于存储库的示例仅显示了如何模拟返回的内容。我有一个有点奇怪的要求:执行查询时,如果存在条件,则应该将某个项目添加到存储库中。我想知道如何在不查询数据库的情况下进行测试。我知道如何模拟现有的条件,但是如何设置模拟以便测试是否添加了某个项目?
问问题
2484 次
5 回答
1
您不会模拟存储库;您将拥有一个备用存储库,该存储库将使用内存存储而不是数据库,然后使用 IoC 为测试/代码选择正确的存储库实现。
于 2012-10-25T16:22:03.427 回答
1
尝试在内存存储库中使用 fake 而不是 moq,例如所有实体的通用通用存储库:
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);
}
}
于 2012-10-25T16:58:22.190 回答
1
这篇博客文章可能有用,尽管自从我写这篇文章后我的设计发生了一些变化,我真的需要更新它。我以一种能够模拟 DbContext 的方式使用了通用存储库模式。这允许“直到边缘”对数据访问层进行测试。
于 2012-10-26T13:45:16.100 回答
0
时代变了——自从Entity Framework 6发布以来,模拟数据库上下文和数据集变得更加容易。 这篇文章概述了细节。
测试非查询场景
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());
}
}
}
测试查询场景 查询测试现在非常好,因为您可以在代码中构建测试数据集,然后针对它们执行测试:
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);
}
}
}
于 2017-06-29T14:53:33.953 回答
0
您可以通过模拟该DbSet.Add()
方法来做到这一点,如下所示:
[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);
}
这改编自此处找到的文档。
于 2020-10-21T01:39:31.083 回答