orleans: Orleans.TestCluster cannot be used at the same time as the unit test. AspNetCore.TestServer is used at the same time.

Orleans.TestCluster cannot be used at the same time as the unit test. AspNetCore.TestServer is used at the same time. Is there any other solution?

            var webHostBuilder = new WebHostBuilder().UseStartup<HttpStartup>();
            this.Server = new TestServer(webHostBuilder);

            var builder = new TestClusterBuilder(1);
            builder.Options.BaseSiloPort = 1000; // this works, while ISiloBuilderConfigurator does not
            builder.Options.BaseGatewayPort = 1001;
            builder.AddClientBuilderConfigurator<ClientBuilderConfigurator>();
            builder.AddSiloBuilderConfigurator<SiloBuilderConfigurator>();
            var cluster = builder.Build();
            cluster.DeployAsync().Wait();
            this.Client = cluster.Client;

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 21 (19 by maintainers)

Most upvoted comments

This is how we worked around it:

        class OrleansInTestsHostBuilder : IHostBuilder
        {
            private readonly IServiceCollection _services;
            private readonly List<Action<HostBuilderContext, IServiceCollection>> _configureDelegates;

            public OrleansInTestsHostBuilder(IServiceCollection services)
            {
                _services = services;

                _configureDelegates = new List<Action<HostBuilderContext, IServiceCollection>>();

                Properties = new Dictionary<object, object>();
            }

            public void Build()
            {
                var context = new HostBuilderContext(Properties);
                foreach (var configureDelegate in _configureDelegates)
                {
                    configureDelegate(context, _services);
                }

                _services.AddSingleton<ITestClusterPortAllocator, TestClusterPortAllocator>();

                _services.AddOptions<EndpointOptions>().Configure<ITestClusterPortAllocator>((options, allocator) =>
                {
                    var ports = allocator.AllocateConsecutivePortPairs(5);
                    options.AdvertisedIPAddress = IPAddress.Loopback;
                    options.SiloPort = ports.Item1;
                    options.GatewayPort = ports.Item2;
                    options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Loopback, options.SiloPort);
                    options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Loopback, options.GatewayPort);
                });
            }

            public IDictionary<object, object> Properties { get; }

            public IHostBuilder ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
            {
                _configureDelegates.Add(configureDelegate);
                return this;
            }

            IHost IHostBuilder.Build() => throw new NotSupportedException();

            IHostBuilder IHostBuilder.ConfigureAppConfiguration(Action<HostBuilderContext, IConfigurationBuilder> configureDelegate) => throw new NotSupportedException();

            IHostBuilder IHostBuilder.ConfigureContainer<TContainerBuilder>(Action<HostBuilderContext, TContainerBuilder> configureDelegate) => throw new NotSupportedException();

            IHostBuilder IHostBuilder.ConfigureHostConfiguration(Action<IConfigurationBuilder> configureDelegate) => throw new NotSupportedException();

            IHostBuilder IHostBuilder.UseServiceProviderFactory<TContainerBuilder>(IServiceProviderFactory<TContainerBuilder> factory) => throw new NotSupportedException();

            IHostBuilder IHostBuilder.UseServiceProviderFactory<TContainerBuilder>(Func<HostBuilderContext, IServiceProviderFactory<TContainerBuilder>> factory) => throw new NotSupportedException();
        }
    }

And then just use UseOrleans:

        TestServer CreateTestServer()
        {
            var hostBuilder = new WebHostBuilder();
            hostBuilder.ConfigureTestServices(services =>
            {
               var builder = new OrleansInTestsHostBuilder(services);
               builder.UseOrleans(...);
               builder.Build();
            });
            return new TestServer(hostBuilder);
        }

Are there problems with this workaround? There’s lots of stuff going on in the Orleans.TestingHost assembly which we skipped. Do you think you could build an API that would not require it? For example, an AddOrleans method that works with IServiceCollection.