NServiceBus.Extensions.IntegrationTesting icon indicating copy to clipboard operation
NServiceBus.Extensions.IntegrationTesting copied to clipboard

Multiple tests not properly isolated?

Open BrandoCaserotti opened this issue 5 years ago • 1 comments

Hi there,

I'm currently testing a saga following the example you have provided in the Wiki.

I am facing a strange issue which is not related to your library but probably to NServiceBus itself.

I've got 2 tests :

[Fact]
public async Task Test_One()
{
   var scenario = Scenario<Test>.CreateScenario()
                                .WithStartingEndpoint("EnpointOne", (s) => {
                                      //Configure some dependecies here
                                })
                                .WithEndpoint("EnpointTwo", (s) => {
                                      //Configure some dependecies here
                                })
                                .WithEndpoint("EnpointThree", (s) => {
                                      //Configure some dependecies here
                                })
                                .Build();

   scenario.Start();

   var message = new Message();

   var result = await ExecuteAndWaitForSagaCompletion<SagaExample>(() => scenario.MessageSession.SendLocal(message));

   scenario.Dispose();

   //Do some assertions
} 

[Fact]
public async Task Test_Two()
{
   var scenario = Scenario<Test>.CreateScenario()
                                .WithStartingEndpoint("EnpointOne", (s) => {
                                      //Configure some dependecies here
                                })
                                .WithEndpoint("EnpointTwo", (s) => {
                                      //Configure some dependecies here
                                })
                                .WithEndpoint("EnpointThree", (s) => {
                                      //Configure some dependecies here
                                })
                                .Build();

   scenario.Start();

   var message = new Message();

   var result = await ExecuteAndWaitForSagaCompletion<SagaExample>(() => scenario.MessageSession.SendLocal(message));

   scenario.Dispose();

   //Do some assertions
} 

In every test I'm spinning up one (or multiple) WebApplicationFactory using the Scenario builder I wrote. Every WebApplicationFactory is configured this way and is properly disposed in every test:

public class ApplicationFactory<T> : WebApplicationFactory<T> where T : class
    {
        private readonly string _endpoint;
        private readonly Action<IServiceCollection> _servicesConfig;

        public ApplicationFactory(string endpoint, Action<IServiceCollection> servicesConfig)
        {
            _endpoint = endpoint;
            _servicesConfig = servicesConfig;
        }

        protected override IHostBuilder CreateHostBuilder() =>
            new HostBuilder()
                .ConfigureServices(_servicesConfig)
                .UseNServiceBus(ctxt =>
                {
                    var endpoint = new EndpointConfiguration(_endpoint);

                    endpoint.ConfigureTestEndpoint();
                    endpoint.UsePersistence<LearningPersistence>();

                    return endpoint;
                })
                .ConfigureWebHost(opts => opts.UseStartup<FakeStartup>());
    }

If I execute the two test one at a time (debugging) everything works as exepected and both tests pass, but if I execute them using a single command (dotnet test) only the first executes correctly (XUnit parallelization is disabled on the entire assembly). The second one sends a message to the error queue containing this exception:

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.CreateScope(IServiceProvider provider)
at NServiceBus.Extensions.Hosting.ServiceProviderAdapter.CreateChildBuilder() in /_/src/NServiceBus.Extensions.Hosting/ServiceProviderAdapter.cs:line 42
at NServiceBus.MainPipelineExecutor.Invoke(MessageContext messageContext)
at NServiceBus.Transport.RabbitMQ.MessagePump.Process(BasicDeliverEventArgs message)

Every test should be isolated from the other one so I don't know what is messing up here, seems like something is shared between the tests I'm running (but what?).

I also tried to change transport (Learning, RabbiMq) but the exception is there anyway Just wanted to know if you are experiencing the same problem.

I'm using NServiceBus 7.2.3 and NServiceBus.Extensions.Hosting 1.1.0 on .Net Core 3.1.10

BrandoCaserotti avatar Nov 27 '20 16:11 BrandoCaserotti

Yeah I'm not sure - it could be the multiple endpoints in a single test, especially as NServiceBus uses assembly scanning to discover handlers and such.

jbogard avatar Nov 30 '20 19:11 jbogard