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

发布于 2024-12-07 05:10:15 字数 1360 浏览 1 评论 0原文

我已在 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。

I have configured Unity in my ASP.NET application and the configuration is loaded when the first request is received in Application_BeginRequest. then the Unity container is stored in the Global.ascx as a property so that my other class can access it:

public static IUnityContainer ContainerHolder { get; set; }

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

ContainerHolder, holds the container instance across application and Container property allows access to this property in each session.

Then I have a UnityLocator class which enables me access this property across the application:

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

Everything works fine!

I have also a method to access the instance from Unity:

UnityLocator.GetInstance<IThemeManager>();

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

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

    }

this has been used in my app so that I can retrieve an existing instance from Unity so that I can inject it to other classes. For example my view (asp.net page) injects this to its Presenter class as a dependency.

Now, I'd like to configure my Unit tests to run.

How could I do that?! global.ascx doesn't exist there obviously so I thought I should create a BaseTest class and let all my tests inherit it. then at the constructor of this BaseTest class, I build up my instances. Is it the right way to do it?

How to configure unit tests with Unity now?

Thanks

UPDATE:
UnityLocator.GetInstance added.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

漫雪独思 2024-12-14 05:10:15

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

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

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

You shouldn't worry about accessing your IoC container. That is a violation of Unit Tests.

Unit tests you should not worry about any concrete implementation or dependency (other than the class under test).

To me, having your IoC globally available is a bad design choice. You should have your dependencies injected via properties or constructors.

找个人就嫁了吧 2024-12-14 05:10:15

使用全局应用程序类来存储服务定位器可能不是一个好主意。为什么不使用内置的 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>();

Probably using the global application class for storing the service locator was not a good idea. Why don't you use the built-in ServiceLocator class? It is available from anywhere in the code and doesn't depend on global application / HttpContext.

Whether or not using the container in unit tests is another story. Personally I am not against it as long as you put stub implementations of your services into the container.

Edit: the way to configure your container using 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;
    }

You can then access the container from within the locator like:

var container = ServiceLocator.Current.GetInstance<IUnityContainer>();
如此安好 2024-12-14 05:10:15

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

public class DepartmentReportPage : Page
{
    private readonly DepartmentReportPresenter _presenter;

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

        this._presenter.View = this;
    }
}

In your page, try doing things like this:

public class DepartmentReportPage : Page
{
    private readonly DepartmentReportPresenter _presenter;

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

        this._presenter.View = this;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文