Search code examples
c#dependency-injectioncastle-windsoraspnetboilerplate

Can't create component as it has dependencies to be satisfied in ASP.NET Boilerplate


I am getting an error while running a test. How do I solve this?

public class TestAppService : TestAppServiceBase, ITestAppService
{
    private readonly ITestRepository _testRepository;
    public TestAppService(ITestRepository testRepository)
    {
        _testRepository = testRepository;
    }
}

public class TestAppService_Test : TestAppServiceTestBase
{
    private readonly ITestAppService _testAppService;
    public TestAppService_Test()
    {
        _testAppService = Resolve<ITestAppService>();
    }
}

The repository:

public class TestRepository : TestRepositoryBase<Test, int>, ITestRepository
{
    private readonly IActiveTransactionProvider _transactionProvider;
    public TestRepository(IDbContextProvider<TestDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }

    public TestRepository(IDbContextProvider<TestDbContext> dbContextProvider,
        IActiveTransactionProvider transactionProvider, IObjectMapper objectMapper)
    : base(dbContextProvider)
    {
        _transactionProvider = transactionProvider;
        ObjectMapper = objectMapper;
    }
}

public interface ITestRepository : IRepository<Test, int>
{
}

public class TestRepositoryBase<TEntity, TPrimaryKey> : EfCoreRepositoryBase<TestDbContext, TEntity, TPrimaryKey>
    where TEntity : class, IEntity<TPrimaryKey>
{
    public IObjectMapper ObjectMapper;
    public TestRepositoryBase(IDbContextProvider<TestDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }
}

/// <summary>
/// Base class for custom repositories of the application.
/// This is a shortcut of <see cref="TestRepositoryBase{TEntity,TPrimaryKey}"/> for <see cref="int"/> primary key.
/// </summary>
/// <typeparam name="TEntity">Entity type</typeparam>
public class TestRepositoryBase<TEntity> : TestRepositoryBase<TEntity, int>
    where TEntity : class, IEntity<int>
{
    public TestRepositoryBase(IDbContextProvider<TestDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }
}

The error:

Test Name:

ABC.XYZ.Tests.PQR.TestAppService_Test.Should_Create_Test_With_Valid_Arguments
Test FullName:  ABC.XYZ.Tests.PQR.TestAppService_Test.Should_Create_Test_With_Valid_Arguments (20f54c54e5d9f077f4cb38b988ecb8e63e07d190)
Test Source:    C:\Users\viveknuna\source\repos\XYZ\aspnet-core\test\ABC.XYZ.Tests\PQR\TestAppService_test.cs : line 25
Test Outcome:   Failed
Test Duration:  0:00:00.001

Result StackTrace:
at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency()
   at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
   at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
   at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
   at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
   at Castle.Windsor.WindsorContainer.Resolve[T]()
   at ABC.XYZ.Tests.PQR.TestAppServiceTestBase..ctor() in C:\Users\viveknuna\source\repos\XYZ\aspnet-core\test\ABC.XYZ.Tests\PQR\TestAppServiceTestBase.cs:line 14
   at ABC.XYZ.Tests.PQR.TestAppService_Test..ctor() in C:\Users\viveknuna\source\repos\XYZ\aspnet-core\test\ABC.XYZ.Tests\PQR\TestAppService_test.cs:line 17
Result Message:
Castle.MicroKernel.Handlers.HandlerException : Can't create component 'ABC.XYZ.Business.Services.PQR.TestAppService' as it has dependencies to be satisfied.

'ABC.XYZ.Business.Services.PQR.TestAppService' is waiting for the following dependencies:
- Service 'ABC.XYZ.Business.Repositories.Interfaces.ITestRepository' which was not registered.

Solution

  • Castle.MicroKernel.Handlers.HandlerException : Can't create component 'ABC.XYZ.Business.Services.PQR.TestAppService' as it has dependencies to be satisfied.

    'ABC.XYZ.Business.Services.PQR.TestAppService' is waiting for the following dependencies:
    - Service 'ABC.XYZ.Business.Repositories.Interfaces.ITestRepository' which was not registered.

    Add DbSet<Test> in your DbContext:

    public class TestDbContext : AbpDbContext
    {
        public DbSet<Test> Tests { get; set; }
    
        public TestDbContext(DbContextOptions<TestDbContext> options)
            : base(options)
        {
        }
    }
    

    Add AutoRepositoryTypes to your DbContext:

    [AutoRepositoryTypes(
        typeof(IRepository<>),
        typeof(IRepository<,>),
        typeof(TestRepositoryBase<>),
        typeof(TestRepositoryBase<,>)
    )]
    public class TestDbContext : AbpDbContext
    {
        ...
    }
    

    Target does not implement interface Abp.Domain.Repositories.IRepository`1[[Abp.Localization.Appl‌​icationLanguage, Abp.Zero.Common, Version=2.3.0.0, Culture=neutral, PublicKeyToken=null]] Parameter name: target

    Register TestRepository:

    Configuration.ReplaceService<IRepository<Test, int>>(() =>
    {
        IocManager.IocContainer.Register(
            Component.For<IRepository<Test, int>, ITestRepository, TestRepository>()
                .ImplementedBy<TestRepository>()
                .LifestyleTransient()
        );
    });
    

    Explanation:

    When you inject ITestRepository, it tries to instantiate IRepository<Test, Int> as defined. However, your TestRepository implements your custom TestRepositoryBase<Test, int>. Therefore, you need to replace IRepository<Test, Int> by registering your concrete class.

    Reference:

    https://aspnetboilerplate.com/Pages/Documents/Entity-Framework-Core#replacing-default-repositories


    Missing type map configuration or unsupported mapping. Mapping types: TestDetailsDTO -> Test Abc.Xyz.Business.Dto.Tests.TestDetailsDTO -> Abc.Xyz.Business.Model.Taxes.Test

    Add [AutoMap(Test)] attribute on TestDetailsDTO.

    If that doesn't work, try to manually configure the mapping:

    public class MyTestModule : AbpModule
    {
        public override void PreInitialize()
        {
            Configuration.Modules.AbpAutoMapper().UseStaticMapper = false;
            Configuration.Modules.AbpAutoMapper().Configurators.Add(config =>
            {
                config.CreateMap<TestDetailsDTO, Test>();
                config.CreateMap<Test, TestDetailsDTO>();
            });
        }
    }