Skip to content

Commit

Permalink
Acceptance test todos (#3994)
Browse files Browse the repository at this point in the history
* Remove the setting of the scenario context since that is done by the endpoint runner already

* Adjust scanning to cores approach and unify templates

* Make base a real base again

* NoRetries
  • Loading branch information
danielmarbach committed Mar 12, 2024
1 parent 7c2e3ab commit 5afc545
Show file tree
Hide file tree
Showing 120 changed files with 487 additions and 1,088 deletions.
@@ -1,33 +1,96 @@
namespace ServiceControl.AcceptanceTesting
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using InfrastructureConfig;
using Microsoft.Extensions.DependencyInjection;
using NServiceBus;
using NServiceBus.AcceptanceTesting.Customization;
using NServiceBus.AcceptanceTesting.Support;
using NServiceBus.Configuration.AdvancedExtensibility;
using NServiceBus.Features;
using NServiceBus.Hosting.Helpers;

public static class EndpointConfigurationExtensions
{
public static void NoImmediateRetries(this EndpointConfiguration configuration)
// This logic has been adapted from Cores ScanTypesForTest to specialize it to the needs of ServiceControl
public static void ScanTypesForTest(this EndpointConfiguration config,
EndpointCustomizationConfiguration customizationConfiguration)
{
configuration.Recoverability().Immediate(x => x.NumberOfRetries(0));
// disable file system scanning for better performance
// note that this might cause issues when required assemblies are only being loaded at endpoint startup time
var assemblyScanner = new AssemblyScanner { ScanFileSystemAssemblies = false };

config.TypesToIncludeInScan(
assemblyScanner.GetScannableAssemblies().Assemblies
.Where(a => !a.FullName!.StartsWith("ServiceControl")) // this prevents handlers, custom checks etc from ServiceControl to be scanned
.Where(a => a != customizationConfiguration.BuilderType.Assembly) // exclude all types from test assembly by default
.SelectMany(a => a.GetTypes())
.Union(GetNestedTypeRecursive(customizationConfiguration.BuilderType.DeclaringType, customizationConfiguration.BuilderType))
.Union(customizationConfiguration.TypesToInclude)
.Except(customizationConfiguration.TypesToExclude)
.ToList());
return;

IEnumerable<Type> GetNestedTypeRecursive(Type rootType, Type builderType)
{
if (rootType == null)
{
throw new InvalidOperationException("Make sure you nest the endpoint infrastructure inside the TestFixture as nested classes");
}

yield return rootType;

if (typeof(IEndpointConfigurationFactory).IsAssignableFrom(rootType) && rootType != builderType)
{
yield break;
}

foreach (var nestedType in rootType.GetNestedTypes(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SelectMany(t => GetNestedTypeRecursive(t, builderType)))
{
yield return nestedType;
}
}
}

public static void NoDelayedRetries(this EndpointConfiguration configuration)
public static async Task DefinePersistence(this EndpointConfiguration config, RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizationConfiguration)
{
configuration.Recoverability().Delayed(x => x.NumberOfRetries(0));
var persistenceConfiguration = new ConfigureEndpointInMemoryPersistence();
await persistenceConfiguration.Configure(endpointCustomizationConfiguration.EndpointName, config, runDescriptor.Settings, endpointCustomizationConfiguration.PublisherMetadata);
runDescriptor.OnTestCompleted(_ => persistenceConfiguration.Cleanup());
}

public static void RegisterComponentsAndInheritanceHierarchy(this EndpointConfiguration builder, RunDescriptor runDescriptor) => builder.RegisterComponents(services => { RegisterInheritanceHierarchyOfContextOnContainer(runDescriptor, services); });

static void RegisterInheritanceHierarchyOfContextOnContainer(RunDescriptor runDescriptor,
IServiceCollection services)
{
var type = runDescriptor.ScenarioContext.GetType();
while (type != typeof(object))
{
services.AddSingleton(type, runDescriptor.ScenarioContext);
type = type.BaseType;
}
}

public static void NoImmediateRetries(this EndpointConfiguration configuration)
=> configuration.Recoverability().Immediate(x => x.NumberOfRetries(0));

public static void NoDelayedRetries(this EndpointConfiguration configuration)
=> configuration.Recoverability().Delayed(x => x.NumberOfRetries(0));

public static void NoRetries(this EndpointConfiguration configuration)
{
configuration.NoDelayedRetries();
configuration.NoImmediateRetries();
}

public static void NoOutbox(this EndpointConfiguration configuration)
{
configuration.DisableFeature<Outbox>();
}
public static void NoOutbox(this EndpointConfiguration configuration) => configuration.DisableFeature<Outbox>();

public static RoutingSettings ConfigureRouting(this EndpointConfiguration configuration) =>
new RoutingSettings(configuration.GetSettings());
new(configuration.GetSettings());
}
}

This file was deleted.

@@ -1,28 +1,23 @@
namespace ServiceControl.AcceptanceTesting.EndpointTemplates
{
using System;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using AcceptanceTesting;
using NServiceBus;
using NServiceBus.AcceptanceTesting;
using NServiceBus.AcceptanceTesting.Customization;
using NServiceBus.AcceptanceTesting.Support;
using NServiceBus.Configuration.AdvancedExtensibility;
using NServiceBus.Features;
using ServiceControl.AcceptanceTesting.InfrastructureConfig;

public class DefaultServerBase<TBootstrapper> : IEndpointSetupTemplate
public abstract class DefaultServerBase(IConfigureEndpointTestExecution endpointTestExecutionConfiguration)
: IEndpointSetupTemplate
{
public DefaultServerBase() : this(new ConfigureEndpointLearningTransport())
protected DefaultServerBase() : this(new ConfigureEndpointLearningTransport())
{
}

public DefaultServerBase(IConfigureEndpointTestExecution endpointTestExecutionConfiguration) => this.endpointTestExecutionConfiguration = endpointTestExecutionConfiguration;

public async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizations, Func<EndpointConfiguration, Task> configurationBuilderCustomization)
public virtual async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointCustomizations, Func<EndpointConfiguration, Task> configurationBuilderCustomization)
{
ServicePointManager.DefaultConnectionLimit = 100;

Expand All @@ -41,8 +36,6 @@ public async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescr
endpointConfiguration.RegisterComponentsAndInheritanceHierarchy(runDescriptor);
await endpointConfiguration.DefinePersistence(runDescriptor, endpointCustomizations);

typeof(ScenarioContext).GetProperty("CurrentEndpoint", BindingFlags.Static | BindingFlags.NonPublic).SetValue(runDescriptor.ScenarioContext, endpointCustomizations.EndpointName);

endpointConfiguration.UseSerialization<NewtonsoftJsonSerializer>();

endpointConfiguration.Pipeline.Register<TraceIncomingBehavior.Registration>();
Expand All @@ -57,20 +50,13 @@ public async Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescr
await configurationBuilderCustomization(endpointConfiguration);

// scan types at the end so that all types used by the configuration have been loaded into the AppDomain
endpointConfiguration.TypesToIncludeInScan(endpointCustomizations.GetTypesScopedByTestClass<TBootstrapper>().Concat(new[]
{
typeof(TraceIncomingBehavior), typeof(TraceOutgoingBehavior)
}).ToList());
endpointConfiguration.ScanTypesForTest(endpointCustomizations);

return endpointConfiguration;
}

static bool IsExternalContract(Type t)
{
return t.Namespace != null && t.Namespace.StartsWith("ServiceControl.Contracts")
&& t.Assembly.GetName().Name == "ServiceControl.Contracts";
}

IConfigureEndpointTestExecution endpointTestExecutionConfiguration;
static bool IsExternalContract(Type t) =>
t.Namespace != null && t.Namespace.StartsWith("ServiceControl.Contracts")
&& t.Assembly.GetName().Name == "ServiceControl.Contracts";
}
}
@@ -0,0 +1,18 @@
namespace ServiceControl.AcceptanceTesting.EndpointTemplates
{
using System;
using System.Threading.Tasks;
using NServiceBus;
using NServiceBus.AcceptanceTesting.Support;

public class DefaultServerWithAudit : DefaultServerBase
{
public override Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointConfiguration, Func<EndpointConfiguration, Task> configurationBuilderCustomization) =>
base.GetConfiguration(runDescriptor, endpointConfiguration, async builder =>
{
builder.AuditProcessedMessagesTo("audit");
await configurationBuilderCustomization(builder);
});
}
}
@@ -0,0 +1,19 @@
namespace ServiceControl.AcceptanceTesting.EndpointTemplates
{
using System;
using System.Threading.Tasks;
using NServiceBus;
using NServiceBus.AcceptanceTesting.Support;
using NServiceBus.Features;

public class DefaultServerWithoutAudit : DefaultServerBase
{
public override Task<EndpointConfiguration> GetConfiguration(RunDescriptor runDescriptor, EndpointCustomizationConfiguration endpointConfiguration, Func<EndpointConfiguration, Task> configurationBuilderCustomization) =>
base.GetConfiguration(runDescriptor, endpointConfiguration, async b =>
{
b.DisableFeature<Audit>();
await configurationBuilderCustomization(b);
});
}
}

This file was deleted.

0 comments on commit 5afc545

Please sign in to comment.