使用Unity容器进行MVC单元测试

时间:2013-01-14 11:56:29

标签: c# asp.net-mvc unit-testing unity-container

我只是一个简单的问题。我试图在我的asp.net MVC项目中使用Unity。我在使用工作单元模式和EF上下文时遇到了问题。

假设我在构造函数中注入了uow,但在控制器中有4或5个动作需要在using语句中使用UnitOfWork。这不会起作用!因为我必须做一个 每个操作方法中new UnitOfWork()

我应该在每个动作方法中注入UnitOfWork吗?或者只是构造函数?或者我甚至应该注射这个!我面临的问题是我希望能够使用Mock数据对我的控制器进行单元测试,而且只有在我注入UnitOfWorkDBContext时才能执行此操作。

2 个答案:

答案 0 :(得分:3)

取而代之的是factory。通过这种方式,您仍然可以实现关注点分离和松散耦合,但使用语句时不会遇到任何问题:

private IUnitOfWorkFactory factory;

public MyController(IUnitOfWorkFactory factory)
{
    this.factory = factory;
}

public ActionResult MyAction()
{
    using (var uow = factory.CreateUnitOfWork())
    {
        // ...
    }
}

修改

这种方法的自然优势在于它的可配置性 - 您可以注册您喜欢的任何工厂,以便为不同的控制器提供服务,并在组合根处进行连接:

// Note: this isn't unity syntax, but I hope my point is clear
container.Register<ISessionFactory, ReusableSessionFactory>("Reusable");
container.Register<ISessionFactory, FreshSessionFactory>("Fresh");
container.Register<IController, LoginController>().With("Fresh");
container.Register<IController, HomeController>().With("Reusable");

现在,

  • LoginController将使用引擎盖下的工厂为每个请求提供新会话
  • 另一方面,
  • HomeController将在其所有生命周期内重复使用相同的会话

值得注意的是,从控制器的角度来看,与工厂为会话服务无关,因为它只是一个实现细节。这就是为什么我们将会话工厂依赖隐藏在抽象(本例中的接口)之后,并在应用程序的根目录下执行所有对象到依赖关系的绑定。

答案 1 :(得分:1)

如果我理解正确你只想用Moq来测试UOW吗?

在这种情况下,为了获得良好的设计原则和正确的关注点分离,您应该为每个存储库类使用的数据库创建一个基本上下文。

然后,您应该为每个域模型实体创建一个存储库接口。然后,您可以在单独的存储库中实现该接口(这样您就可以实现POCO模型)

最后,您要么在域对象和操作方法之间创建服务层,要么只在操作方法中使用所需的存储库接口。

我这样回答是因为它取决于您的应用程序基础架构。如果您没有服务层,那么最佳做法是执行以下操作:

   public class AccountController : Controller
    {
        private readonly IAccountRepository _accountrepository;

        public AccountController(IAccountRepository repository)
        {
            _accountrepository = repository;
        }
}

我希望这会有所帮助。