简体   繁体   中英

How to configure unit tests with an IoC container in ASP.NET?

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.

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.

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>();

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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM