2

我正在学习 DI、IoC 和 MOQ,所以我可以 TDD 我的新 MVC4 应用程序。

我在网上关注了很多示例,但有一件事我无法掌握。

我的应用程序由 3 层(物理项目)组成:

  1. 应用层(控制器/模型/标准 MVC4 东西)。
  2. 业务层(做所有的计算和处理数据)。
  3. DAL (EF5)。

现在我有一个非常简单的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.
    }
}

现在我需要访问我可以在我UserRepository的 Get 方法中执行的 DAL。

只有我如何对此进行单元测试?由于可测试性,我认为类中不应该存在依赖关系。

如果我在单元测试中使用实际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);
    }
}
4

3 回答 3

3

存储库是通往数据库的网关。它们包含尽可能少的代码(没有业务内容),并且只做将数据从数据库中取出(或将其保存到数据库中)所需的操作。

由于它直接耦合到您的数据库,因此您无法对其进行单元测试。当您抽象出该逻辑时,您只能对其进行单元测试,但这正是存储库的用途,因此这是一个无用的抽象。

相反,为他们编写集成测试以设置数据库事务并调用真实存储库并在完成后回滚该事务。

于 2012-10-20T15:22:54.543 回答
0

编写一个返回适当数据的模拟 IUserRepository,但老实说,您可以轻松地模拟 EF4 及以后的基础数据,因此您可以根据需要直接在控制器中测试您的 EF 查询。在 EF4 中,您将 ObjectSet 替换为实现了 IObjectSet 的假 ObjectSet - 我相当确定使用 EF5 您可以使用 DbSet 执行相同的操作。

于 2012-10-20T21:14:34.687 回答
0

如果我们使用 Unity。我们可以在中间层实现一个 Unity 容器的扩展,并像下面这样在 Presentation 层注册。

          //Data Layer dependency mapping as extension eg : IUnitOfWork
            container.AddNewExtension<DependencyInjectionExtension>();

更多详情请关注文章。

N 层与 DI (Unity)

谢谢

于 2017-04-16T13:54:09.040 回答