Search code examples
c#entity-frameworkinversion-of-controlunity-container

Multiple constructors -parameter cannot be constructed


In the data layer on an ASP.Net MVC site, I have the following "default" constructor:

public class UserPrefsContext : DbContext
{
    private static ILog _logger =
        LogManager.GetLogger(
        System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    public UserPrefsContext()
        : base("Unit4.UserPrefsConString")
    {
        this.Configuration.LazyLoadingEnabled = false;

        _logger.DebugFormat("Connection string being used for UserPrefs db:{0}", Database.Connection.ConnectionString);
        Database.SetInitializer<UserPrefsContext>(null);

    }
}

I've been using Unity as an IoC container and Moq to mock data context object which get injected into the controllers. This has worked ok for unit tests but for broader integration tests (between the website and database) I'd like the context to work against a "real" test database.

So, I've added the following 2nd constructor:

public UserPrefsContext(string testConString)
    {
        this.Configuration.LazyLoadingEnabled = false;
        this.Database.Connection.ConnectionString = testConString;

        _logger.DebugFormat("Connection string being used for UserPrefs db:{0}", Database.Connection.ConnectionString);
        Database.SetInitializer<UserPrefsContext>(null);
    }

My tests work ok but when I run the website I now get the error message "The type String cannot be constructed. You must configure the container to supply this value". It seems "something" is trying to create a UserPrefsContext object with the 2nd constructor. My guess is the "something" is System.Web.Mvc.DepnedencyResolver. Here is the code from a Bootstrapper.cs file in the website root:

public class Bootstrapper
{
    public static IUnityContainer Initialise()
    {
        var container = BuildUnityContainer();
        log4net.Config.XmlConfigurator.Configure();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // e.g. container.RegisterType<ITestService, TestService>();    
        RegisterTypes(container);

        return container;
    }

    public static void RegisterTypes(IUnityContainer container)
    {
        container.RegisterType<IESBContext, ESBContext>();
        container.RegisterType<IConfigurationManager, WebConfigConfigurationManager>();
    }
}

How can I solve this please?


Solution

  • I was approaching this from wrong direction.

    Solution was to have the single parameter-less constructor for the controllers. The integration test project now calls the bootstrapper class to ensure unity creates the required db context objects.

    I then added connection strings to the app.config of the integration test project and changed these to point at special test instances of each context's database. I am able to pre-load these with data saved as a .sql script in the integration test project.