我正在学习DI,IoC和MOQ,所以我可以TDD我的新MVC4应用程序。
我在网上关注了很多例子,但有一件事我无法理解。
我的应用程序由3层(物理项目)组成:
现在我有一个非常简单的UserController
public class UserController : Controller
{
readonly IUserRepository _repository;
public UserController(IUserRepository rep)
{
_repository = rep;
}
public ActionResult Index()
{
IList<User> users = _repository.Get(10);
return View(users);
}
使用Unity注入依赖关系,这很好。
在业务层中,我有存储库:
public interface IUserRepository
{
IList<User> Get(Int32 count);
}
public class UserRepository : IUserRepository
{
public IList<User> Get(Int32 count)
{
// Here I fetch the data from the Database
// and do some stuff with it, this can be
// quite a big method.
}
}
现在我需要访问我的DAL,我可以在UserRepository
的Get方法中执行此操作。
我该如何对此进行单元测试?由于可测试性,我认为在课堂上不应该存在依赖性。
如果我在单元测试中使用实际的UserRepository
类进行测试,它将转到DAL并使用那里的数据,但我需要模拟数据。
我是否需要创建另一个IUserDataRepository
,从数据库中提取实际数据并将其传递到UserRepository
构造函数中,或者我应该使用Unity来处理这个问题?
可能的答案?
我创建了一个名为Users
的新界面:
public class Users: IUsers
{
private readonly IUserRepository _userRepository;
public Users(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public User Get(String id)
{
// Do all the magic here here
}
}
从此界面IUsers
:
public interface IUsers
{
User Get(String id);
}
但是我将面向数据库的存储库移到了DAL:
public class UserRepository : IUserRepository
{
public User Get(String id)
{
// Retrieve the user from the database with EF5
}
}
public interface IUserRepository
{
User Get(String id);
}
控制器保持不变,但现在依赖于IUser接口:
public class UserController : Controller
{
readonly IUsers _users;
public UserController(IUsers users)
{
_users = users;
}
public ActionResult Index()
{
User user = _users.Get(10);
return View(users);
}
}
答案 0 :(得分:3)
存储库是数据库的网关。它们包含尽可能少的代码(没有业务),只需要从数据库中获取数据(或将数据保存到数据库中)。
由于它直接耦合到您的数据库,因此您无法对其进行单元测试。你只能在抽象逻辑时对其进行单元测试,但这正是存储库的用途,因此这是一种无用的抽象。
相反,为它们编写集成测试,设置数据库事务并调用真实存储库并在完成后回滚该事务。
答案 1 :(得分:0)
编写一个返回相应数据的模拟IUserRepository,但老实说,您可以轻松地在EF4中模拟基础数据,这样您就可以直接在控制器中测试您的EF查询。在EF4中,您使用实现IObjectSet的伪ObjectSet替换ObjectSet - 我相当确定使用EF5可以对DbSet执行相同的操作。
答案 2 :(得分:0)
如果我们使用Unity。我们可以在中间层实现Unity容器的扩展,并在Presentation层中注册,如下所示。
//Data Layer dependency mapping as extension eg : IUnitOfWork
container.AddNewExtension<DependencyInjectionExtension>();
更多详情请关注文章。
由于