mercredi 4 mai 2016

Autofac RegisterGeneric works in unit test but not in application

I've got an ASP.NET MVC 6 (Framework 4.6.1) application with Autofac version 4.0.0-rc1-177.

In my Startup.cs, I call an AutofacLoader I've made:

var container = Core.DI.AutofacLoader.Configure(services).Build();

The AutofacLoader class:

public class AutofacLoader
{
    public static IContainer Container { get; set; }

    /// <summary>
    /// Register the DI modules through AutoFac
    /// </summary>
    /// <param name="services">IServiceCollection to register the modules on</param>
    /// <returns></returns>
    public static ContainerBuilder Configure(IServiceCollection services)
    {
        var builder = new ContainerBuilder();

        builder.RegisterModule<LogRequestsModule>();
        //Core
        builder.RegisterModule(new Core.ServiceModules.AutoMapperModule());
        builder.RegisterModule(new Core.ServiceModules.ServicesModule());
        builder.RegisterModule(new DAL.ServicesModules.IBSRepositoriesModule());

        //Dieet
        builder.RegisterModule(new Dieet.Core.ServiceModules.AutoMapperModule());
        builder.RegisterModule(new Dieet.Core.ServiceModules.ServicesModule());
        builder.RegisterModule(new Dieet.DAL.ServicesModules.DieetRepositoriesModule());

        //builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
        if (services == null)
        {
            Container = builder.Build();
        }
        else
        {
            builder.Populate(services);

        }
        return builder;
    }
}

My IBS.Core.ServicesModules.ServiceModule class (which when I put a breakpoint in this class, gets called when launching my app, so by the AutofacLoader class):

namespace IBS.Core.ServiceModules
{
    public class ServicesModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            var assembly = System.Reflection.Assembly.GetExecutingAssembly();
            builder.RegisterAssemblyTypes(assembly)
                .Where(t => t.Name.EndsWith("Service"))
                .AsImplementedInterfaces();
            builder.RegisterGeneric(typeof(PaginatedSearchViewModel<>)).As(typeof(IPaginatedSearchViewModel<>)).InstancePerLifetimeScope();
        }
    }
}

My xunit test (with FluentAssertions) that passes:

public class ServiceModulesTest
{
    [Fact]
    public void ShouldBeInstantiatable()
    {
        AutofacLoader.Configure(null);
        var container = AutofacLoader.Container;
        var instance = container.Resolve<IPaginatedSearchViewModel<PatientViewModel>>();

        instance.Should().BeOfType<PaginatedSearchViewModel<PatientViewModel>>();
    }
}

But when I run the application, in one of my API controllers, I've got for example, this method:

    [HttpGet("patienten")]
    public async Task<PagedResult<PatientViewModel>> GetPatientsAsync(IPaginatedSearchViewModel<PatientFilters> vm)
    {
        return await _infohosService.GetAllPatientsWithDossiersAndVerpleegperiodesAsync(vm);
    }

This fails in the browser with the response: Cannot resolve the Interface.

When I change the IPaginatedSearchViewModel to the concrete class in the parameters myself:

    [HttpGet("patienten")]
    public async Task<PagedResult<PatientViewModel>> GetPatientsAsync(PaginatedSearchViewModel<PatientFilters> vm)
    {
        return await _infohosService.GetAllPatientsWithDossiersAndVerpleegperiodesAsync(vm);
    }

The API works.

So my questions:

  1. Why does my unit test pass? (I'm new to unit testing, so maybe I've done something wrong here?)

  2. How can I make Autofac resolve this Interface too, because it works fine for all my Services, Repositories, IDbContext, ...?

Aucun commentaire:

Enregistrer un commentaire