我有一个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;
}
}
答案 0 :(得分:2)
实现
目标的一种方法我想这样做,因为它使我能够控制交易和上下文处理。
将按照
的方式做点什么public class UserService : IUserService {
private ContextFactory _ContextFactory;
public UserService(ContextFactory contextFactory) {
_ContextFactory = contextFactory;
}
public void AddUser(UserModel userModel) {
...
using (var context = _ContextFactory.CreateInstance()) {
context.Users.Add(user);
}
}
}
这将允许您注入ContextFactory
的不同实例,这些实例将使用模拟创建DbContext
答案 1 :(得分:1)
我绝对会更喜欢IOC方法但是如果你想要一个快速解决方案而不需要重写太多代码,你可以做这样的事情:
public class UserService : IUserService
{
public static Func<MyDbContext> CreateContext = () => new MyDbContext();
public UserService ()
{
}
public void AddUser(UserModel userModel)
{
...
using (var context = CreateContext())
{
context.Users.Add(user);
}
}
}
您不必更改生产代码,但在TestMethod中可以执行
var context = new MyDbContext
{
Users = userSet
};
UserService.CreateContext = () => context;
答案 2 :(得分:0)
您需要在服务的构造函数中传递 DbContext 。最简单的方法是开始使用任何IoC框架(AutoFac,Unity,Ninject等)。要模拟数据库,最简单的方法是开始使用任何模拟库,如Moq和RhinoMocks。
public class UserService : IUserService
{
private MyDbContext _context;
public UserService (MyDbContext dbContext)
{
_context = dbContext;
}
}