【发布时间】:2015-08-20 05:28:27
【问题描述】:
我有一个 ASP.NET MVC 项目,并且正在按照以下内容编写我的服务:
public class UserService : IUserService
{
public void AddUser(UserModel userModel)
{
if (ModelState.IsValid){
var user = new User
{
FirstName = userModel.FirstName,
LastName = userModel.LastName,
Email = userModel.Email,
Age = userModel.Age
};
using (var context = new MyDbContext())
{
context.Users.Add(user);
}
}
}
//... More code for service
}
还有我的 DbContext 类:
public class MyDbContext : DbContext
{
public MyDbContext(): base("name=mydb"){}
public DbSet<User> Users {get; set;}
//.. More domain objects.
}
这在大多数情况下运行良好,但是当我想尝试测试它时就会出现问题。我遵循一般准则here 将其模拟出来,但前提是 DbContext 被声明为类实例,而不是函数变量。我想这样做是因为它使我能够控制事务和上下文处理。有人对如何做到这一点有任何建议吗?
我的模拟是这样的:
public class UserServiceTest
{
[Fact]
public void TestAddUser()
{
var userSet = GetQueryableMockDbSet(userData.ToArray());
var context = new MyDbContext
{
Users = userSet
};
var userService = new UserService();
userService.AddUser(); // HOW DO I GET CONTEXT IN HERE?
}
private static DbSet<T> GetQueryableMockDbSet<T>(params T[] sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
return dbSet.Object;
}
}
【问题讨论】:
-
您需要将
DbContext传递给服务的构造函数。阅读依赖注入并使用一些 IoC 容器使事情变得更容易 -
他不能将实例传递给容器,因为他说他想控制方法内实例的创建。我在想也许 OP 可以将
Factory注入将创建实例的服务中,然后使用模拟对象模拟工厂创建方法 -
工厂方法看起来很有希望:它会不会像 FactoryContext.Create() 返回一个 MyDbContext 项? Create 方法显然是静态的。
-
是的@IvanPeng 这正是我的想法,请参阅下面的答案
标签: c# asp.net-mvc integration-testing