C# 如何在ASP.NET中使用IoC容器配置单元测试?

C# 如何在ASP.NET中使用IoC容器配置单元测试?,c#,asp.net,unit-testing,unity-container,C#,Asp.net,Unit Testing,Unity Container,我已经在ASP.NET应用程序中配置了Unity,并且在应用程序_BeginRequest中收到第一个请求时加载配置。然后Unity容器作为属性存储在Global.ascx中,以便我的其他类可以访问它: public static IUnityContainer ContainerHolder { get; set; } IUnityContainer IContainerAccessor.Container { get { return ContainerHolder; } } C

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

public static IUnityContainer ContainerHolder { get; set; }

IUnityContainer IContainerAccessor.Container
{
    get { return ContainerHolder; }
}
ContainerHolder跨应用程序保存容器实例,容器属性允许在每个会话中访问此属性

然后我有一个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检索现有实例,以便将其注入其他类。例如,my view asp.net页面将此作为依赖项注入其Presenter类

现在,我想将我的单元测试配置为运行

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

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

谢谢

更新:
添加了UnityLocator.GetInstance。

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

单元测试您不应该担心任何具体的实现或依赖性,除了被测试的类之外


对我来说,让国际奥委会在全球范围内运行是一个糟糕的设计选择。您应该通过属性或构造函数注入依赖项。

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

单元测试您不应该担心任何具体的实现或依赖性,除了被测试的类之外


对我来说,让国际奥委会在全球范围内运行是一个糟糕的设计选择。您应该通过属性或构造函数注入依赖项。

使用全局应用程序类存储服务定位器可能不是一个好主意。为什么不使用内置的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类?它可以从代码中的任何地方获得,并且不依赖于全局应用程序/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>();

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

public class DepartmentReportPage : Page
{
    private readonly DepartmentReportPresenter _presenter;

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

        this._presenter.View = this;
    }
}

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

public class DepartmentReportPage : Page
{
    private readonly DepartmentReportPresenter _presenter;

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

        this._presenter.View = this;
    }
}

什么意思?现在如何配置和运行我的单元测试?@William-您使用的是mvc还是web表单?web表单,mvp。我意识到我在代码中使用的是UnityLocator.GetInstance方法,所以我将对其进行重构,并将其移动到仅查看页面。为什么您的视图依赖于某些内容?我同意Daniel的观点,您不应该在单元测试中使用容器。只需在测试的类中手动注入依赖项。当您为所有测试配置了一个全局配置的容器时,您将陷入维护噩梦。您是什么意思?现在如何配置和运行我的单元测试?@William-您使用的是mvc还是web表单?web表单,mvp。我意识到我在代码中使用的是UnityLocator.GetInstance方法,所以我将对其进行重构,并将其移动到仅查看页面。为什么您的视图依赖于某些内容?我同意Daniel的观点,您不应该在单元测试中使用容器。只需在测试的类中手动注入依赖项。当您为所有测试配置了一个全局配置的容器时,您将陷入一场维护噩梦。也许概述一下IoC解决的问题将是一个良好的开端。如果你理解了问题域,那么你就可以更清楚地理解为什么你不需要在单元测试中关注IoC容器。也许对IoC解决的问题的概述是一个好的开始。如果您理解了问题域,那么就可以更清楚地理解为什么您不需要在单元测试中关注IoC容器。我们在哪里可以找到这个ServiceLocator类?你说它是内置的。内置于什么。网ASP.NET?谢谢,我要用
内置ServiceLocator:我对您的建议唯一的问题是,我下面的方法在这种情况下不起作用:public static void InjectDependenciesT existingType{Container.BuildUpexistingType;},即注入类型的依赖项。ServiceLocator不允许我访问容器;您将如何解决此问题?您应该能够从包含ServiceLocator.Current.GetInstance的容器中获取一个。我们在哪里可以找到此ServiceLocator类?你说它是内置的。内置于什么。网ASP.NET?谢谢,我将用内置的ServiceLocator替换我的UnityLocator:你的建议中唯一的问题是我下面的方法在这种情况下不起作用:public static void InjectDependenciesT existingType{Container.BuildUpexistingType;}即注入类型的依赖项。ServiceLocator不允许我访问容器;您将如何解决此问题?您应该能够使用ServiceLocator.Current.GetInstance从容器中获取一个。