【发布时间】:2014-09-01 15:35:03
【问题描述】:
我正在尝试使用Moq 测试方法DepartmentSerive.SearchAsync(string name)。到目前为止,我已经关注了这个 msdn tutorial 关于如何模拟 DbSet 和 ApplicationDbContext 类。
首先,我复制了DbAsyncQueryProvider 的实现,所以我可以使用异步方法。
然后我实现了我的DepartmentService : Service<TEntity> 类。
public class DepartmentService : Service<Department>
{
public DepartmentService(ApplicationDbContext db) : base(db) { }
public async Task<ICollection<Department>> SearchAsync(string name)
{
if (String.IsNullOrEmpty(name))
{
return await AllAsync();
}
return await db.Departments
.Where(d => d.Name.ToLower().Contains(name.ToLower()))
.OrderBy(d => d.Name)
.ToListAsync();
}
}
Service<TEntity> 是一个通用服务,具有AllSync、Insert、Update、Delete 等方法,但相关部分在这里:
public abstract class Service<TEntity> where TEntity : class
{
public virtual async Task<ICollection<TEntity>> AllAsync()
{
return await db.Set<TEntity>().ToListAsync();
}
}
我有一个Setup 方法:
[TestInitialize]
public void Setup()
{
var data = new List<Department>
{
new Department { Id = 1, Name = "Computer Science" },
new Department { Id = 2, Name = "Political Science" },
new Department { Id = 3, Name = "Physics" },
new Department { Id = 4, Name = "Mathematics" },
}.AsQueryable();
var set = new Mock<DbSet<Department>>();
set.As<IDbAsyncEnumerable<Department>>().Setup(m => m.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<Department>(data.GetEnumerator()));
set.As<IQueryable<Department>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<Department>(data.Provider));
set.As<IQueryable<Department>>().Setup(m => m.Expression).Returns(data.Expression);
set.As<IQueryable<Department>>().Setup(m => m.ElementType).Returns(data.ElementType);
set.As<IQueryable<Department>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
context = new Mock<ApplicationDbContext>();
context.Setup(c => c.Set<Department>()).Returns(set.Object);
context.Setup(c => c.Departments).Returns(set.Object);
}
最后是我的测试:
[TestMethod]
public async Task SearchWithEmptyString()
{
var service = new DepartmentService(context.Object);
var result = await service.SearchAsync(null);
Assert.AreEqual(4, result.Count);
result = await service.SearchAsync("");
Assert.AreEqual(4, result.Count);
}
我的测试应该通过,考虑到null 和"" 将由SearchAsync() 以相同的方式处理,但实际上在第二个Assert.AreEqual(4, result.Count); 上失败了。出于某种原因,服务中对AllAsync() 的第一次调用会返回整个列表,但第二次调用会返回一个空列表,就好像AllAsync() 正在返回元素一样,但在此过程中也会清空列表。
当我使用真实数据库时,不会发生此问题。我在DepartmentController 处写了两个连续的AllAsync(),第二个仍然返回正确的数据。
在模拟列表或设置测试时,我做错了吗?
【问题讨论】:
标签: c# unit-testing mocking asp.net-mvc-5 entity-framework-6