Base solution for your next web application
Open Closed

Unit Testing with Multitenancy and tenant per DB #1791


User avatar
0
carelearning created

Hello,

I am trying to write unit tests in a situation where we have multiple tenants and each tenant has its own database. Not matter what is tried, this error keeps getting thrown: Castle.MicroKernel.ComponentActivator.ComponentActivatorException ComponentActivator: could not instantiate We start the test like this:

namespace MyCompanyName.AbpZeroTemplate.Tests.Migration
{
    using AbpZeroTemplate.Migration;
    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Xunit;

    public class MigrationAppService_Tests : AppTestBase
    {
        private readonly IMigrationAppService _migrationAppService;

        public MigrationAppService_Tests()
        {
            LoginAsHostAdmin();
            
            _migrationAppService = Resolve<IMigrationAppService>();
        }

        [Fact]
        public async Task IfTenantIsMissingSaveZipAsyncThrowsException()
        {
            await _migrationAppService.SaveZipAsync(1, new MemoryStream(), String.Empty);
        }
    }
}

The "stystem under test" is a service here:

namespace MyCompanyName.AbpZeroTemplate.Migration
{
    using Abp.Domain.Repositories;
    using MultiTenancy;
    using System;
    using System.IO;
    using System.Threading.Tasks;

    public class MigrationAppService : AbpZeroTemplateAppServiceBase, IMigrationAppService
    {
        private readonly IRepository<Tenant> _tenantRepository;

        public MigrationAppService(IRepository<Tenant> tenantRepository)
        {
            _tenantRepository = tenantRepository;
        }

        public async Task SaveZipAsync(int id, Stream stream, string path)
        {
            var tenant = await _tenantRepository.GetAsync(id);
            if (tenant == null)
                throw new Exception($"Tenant with {id} was not found.");
        }
    }
}

The tenant and host DB context is attached. It appears that the error surfaces in AbpZeroTemplateTenantDbContext.AbpZeroTemplateTenantDbContext() and might be trying to use the tenant context instead of the host. The 15 lines of the error is:

Castle.MicroKernel.ComponentActivator.ComponentActivatorException
ComponentActivator: could not instantiate MyCompanyName.AbpZeroTemplate.EntityFramework.AbpZeroTemplateTenantDbContext
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstanceCore(ConstructorCandidate constructor, Object[] arguments, Type implType)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.CreateInstance(CreationContext context, ConstructorCandidate constructor, Object[] arguments)
   at Castle.MicroKernel.ComponentActivator.DefaultComponentActivator.InternalCreate(CreationContext context)
   at Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.Create(CreationContext context, Burden burden)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.CreateInstance(CreationContext context, Boolean trackedExternally)
   at Castle.MicroKernel.Lifestyle.AbstractLifestyleManager.Resolve(CreationContext context, IReleasePolicy releasePolicy)
   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 Abp.EntityFramework.DefaultDbContextResolver.Resolve[TDbContext](String connectionString) in D:\Halil\GitHub\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\DefaultDbContextResolver.cs:line 30
   at Abp.EntityFramework.Uow.EfUnitOfWork.GetOrCreateDbContext[TDbContext](Nullable`1 multiTenancySide) in D:\Halil\GitHub\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\Uow\EfUnitOfWork.cs:line 130
   at Castle.Proxies.EfRepositoryBase`3Proxy_14.get_Context_callback()

Can you advise on how to write this simple unit test or how to avoid this error?

Thank you for your help. DBContexts.zip


3 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I have tried with your DbContexes and tests worked. But I just removed configurations for TenantDbContext (DepartmentConfiguration and EnrollmentConfiguration).

    Can you send the full project via email if it is not a problem ? In that way, we can help more quickly.

  • User Avatar
    0
    carelearning created

    We have worked around this using mocking, but still wonder if we did something wrong. We need this for real integration tests and TDD. I will send you a PM on this board to ask for your email address. Thanks.

  • User Avatar
    0
    carelearning created

    We are still approaching this issue with mocking out the repositories. Therefore, we will post back with a solution if this becomes a bigger challenge.

    Thank you again for your help.