【问题标题】:How to configure unit tests with an IoC container in ASP.NET?如何在 ASP.NET 中使用 IoC 容器配置单元测试?
【发布时间】:2011-09-29 12:32:31
【问题描述】:

我已经在我的 ASP.NET 应用程序中配置了 Unity,并且在 Application_BeginRequest 中收到第一个请求时加载了配置。然后 Unity 容器作为属性存储在 Global.ascx 中,以便我的其他类可以访问它:

public static IUnityContainer ContainerHolder { get; set; }

IUnityContainer IContainerAccessor.Container
{
    get { return ContainerHolder; }
}

ContainerHolder,跨应用保存容器实例,Container 属性允许在每个会话中访问该属性。

然后我有一个 UnityLocator 类,它使我能够跨应用程序访问此属性:

public static class UnityLocator
    {        
        private static IUnityContainer Container
        {
            get
            {
                return ((IContainerAccessor)HttpContext.Current.ApplicationInstance).Container;
            }
        }
    }

一切正常!

我还有一个从 Unity 访问实例的方法:

UnityLocator.GetInstance<IThemeManager>();

    protected Repository(ICustomCacheManager customCacheManager)
    {
        this.Cache = customCacheManager;
    }

    protected Repository()
        : this(UnityLocator.GetInstance<ICustomCacheManager>())
    {

    }

这已在我的应用程序中使用,以便我可以从 Unity 检索现有实例,以便将其注入其他类。例如,我的视图(asp.net 页面)将此作为依赖项注入到它的 Presenter 类中。

现在,我想配置我的单元测试以运行。

我怎么能这样做?! global.ascx 显然不存在,所以我想我应该创建一个 BaseTest 类并让我所有的测试继承它。然后在这个 BaseTest 类的构造函数中,我构建了我的实例。这是正确的做法吗?

现在如何使用 Unity 配置单元测试?

谢谢

更新: 已添加 UnityLocator.GetInstance。

【问题讨论】:

  • 也许对 IoC 解决的问题的概述是一个好的开始。如果您了解问题域,那么它将更清楚为什么您不需要在单元测试中关注 IoC 容器。

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


【解决方案1】:

您不必担心访问您的 IoC 容器。这违反了单元测试。

单元测试你不应该担心任何具体的实现或依赖(除了被测试的类)。

对我来说,让您的 IoC 全球可用是一个糟糕的设计选择。您应该通过属性或构造函数注入依赖项。

【讨论】:

  • 什么意思?现在如何配置和运行我的单元测试?
  • @William - 你使用的是 mvc 还是 web 表单?
  • 网络表单,mvp。我意识到我在代码中使用了 UnityLocator.GetInstance 方法,因此我将对其进行重构并将它们仅移动到视图(页面)。
  • 为什么你的观点依赖于某些东西?
  • 我同意 Daniel 的观点,即您不应该在单元测试中使用容器。只需在被测类中手动注入依赖项即可。当您为所有测试都配置了一个全局配置的容器时,您将陷入维护的噩梦。
【解决方案2】:

可能使用全局应用程序类来存储服务定位器不是一个好主意。为什么不使用内置的 ServiceLocator 类?它可以在代码中的任何地方使用,并且不依赖于全局应用程序/HttpContext。

在单元测试中是否使用容器是另一回事。只要您将服务的存根实现放入容器中,我个人并不反对。

编辑:使用 ServiceLocator 配置容器的方式:

    private void ConfigureUnity()
    {
        UnityServiceLocator locator = new UnityServiceLocator( ConfigureUnityContainer() );
        ServiceLocator.SetLocatorProvider( () => locator );
    }

    private IUnityContainer ConfigureUnityContainer()
    {
        IUnityContainer container = new UnityContainer();

        // this loads container's configuration, comment or uncomment
        container.LoadConfiguration();

        return container;
    }

然后您可以从定位器中访问容器,例如:

var container = ServiceLocator.Current.GetInstance<IUnityContainer>();

【讨论】:

  • 我们在哪里可以找到这个ServiceLocator 类?你说它是内置的。内置于什么? 。网? ASP.NET?
  • 谢谢,我打算用内置的 ServiceLocator 替换我的 UnityLocator:blogs.msdn.com/b/miah/archive/2009/05/12/…
  • 我对你的建议的唯一问题是我下面的方法在这种情况下不起作用: public static void InjectDependencies(T existingType) { Container.BuildUp(existingType); } 就是注入一个类型的依赖。
  • ServiceLocator 不允许我访问容器;你将如何解决这个问题?
  • 你应该可以使用ServiceLocator.Current.GetInstance&lt;IUnityContainer&gt;()从容器中获取一个。
【解决方案3】:

在您的页面中,尝试执行以下操作:

public class DepartmentReportPage : Page
{
    private readonly DepartmentReportPresenter _presenter;

    public DepartmentReportPage()
    {
        this._presenter =
            UnityLocator.GetInstance<DepartmentReportPresenter>();

        this._presenter.View = this;
    }
}

【讨论】:

    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-02
    • 2011-02-09
    • 2010-11-30
    相关资源
    最近更新 更多