diff --git a/src/NServiceBus.IntegrationTesting/EndpointConfigurationExtensions.cs b/src/NServiceBus.IntegrationTesting/EndpointConfigurationExtensions.cs new file mode 100644 index 00000000..9e823b40 --- /dev/null +++ b/src/NServiceBus.IntegrationTesting/EndpointConfigurationExtensions.cs @@ -0,0 +1,31 @@ +using NServiceBus.AcceptanceTesting; +using NServiceBus.ObjectBuilder; + +namespace NServiceBus.IntegrationTesting +{ + public static class EndpointConfigurationExtensions + { + public static void RegisterRequiredPipelineBehaviors(this EndpointConfiguration builder, string endpointName, IntegrationScenarioContext integrationScenarioContext) + { + builder.Pipeline.Register(new InterceptInvokedHandlers(endpointName, integrationScenarioContext), "Intercept invoked Message Handlers and Sagas"); + builder.Pipeline.Register(new InterceptSendOperations(endpointName, integrationScenarioContext), "Intercept send operations"); + builder.Pipeline.Register(new InterceptPublishOperations(endpointName, integrationScenarioContext), "Intercept publish operations"); + builder.Pipeline.Register(new InterceptReplyOperations(endpointName, integrationScenarioContext), "Intercept reply operations"); + } + + public static void RegisterScenarioContext(this EndpointConfiguration builder, ScenarioContext scenarioContext) + { + builder.RegisterComponents(r => { RegisterInheritanceHierarchyOfContextOnContainer(scenarioContext, r); }); + } + + static void RegisterInheritanceHierarchyOfContextOnContainer(ScenarioContext scenarioContext, IConfigureComponents r) + { + var type = scenarioContext.GetType(); + while (type != typeof(object)) + { + r.RegisterSingleton(type, scenarioContext); + type = type.BaseType; + } + } + } +} diff --git a/src/NServiceBus.IntegrationTesting/EndpointTemplate.cs b/src/NServiceBus.IntegrationTesting/EndpointTemplate.cs index 6402ed6b..7327884a 100644 --- a/src/NServiceBus.IntegrationTesting/EndpointTemplate.cs +++ b/src/NServiceBus.IntegrationTesting/EndpointTemplate.cs @@ -1,5 +1,7 @@ -using NServiceBus.AcceptanceTesting.Support; +using NServiceBus.AcceptanceTesting.Customization; +using NServiceBus.AcceptanceTesting.Support; using NServiceBus.Configuration.AdvancedExtensibility; +using NServiceBus.IntegrationTesting.Messages.Handlers; using System; using System.Threading.Tasks; @@ -13,13 +15,16 @@ public async Task GetConfiguration(RunDescriptor runDescr var settings = configuration.GetSettings(); endpointCustomizationConfiguration.EndpointName = settings.EndpointName(); - configurationBuilderCustomization(configuration); - configuration.Pipeline.Register(new InterceptInvokedHandlers(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext), "Intercept invoked Message Handlers and Sagas"); - configuration.Pipeline.Register(new InterceptSendOperations(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext), "Intercept send operations"); - configuration.Pipeline.Register(new InterceptPublishOperations(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext), "Intercept publish operations"); - configuration.Pipeline.Register(new InterceptReplyOperations(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext), "Intercept reply operations"); + configuration.TypesToIncludeInScan(new[] + { + typeof(CreateSagaInstanceHandler), + typeof(MarkSagaInstanceAsCreatedHandler) + }); + + configuration.RegisterScenarioContext(runDescriptor.ScenarioContext); + configuration.RegisterRequiredPipelineBehaviors(endpointCustomizationConfiguration.EndpointName, (IntegrationScenarioContext)runDescriptor.ScenarioContext); return configuration; } diff --git a/src/NServiceBus.IntegrationTesting/IntegrationScenarioContext.cs b/src/NServiceBus.IntegrationTesting/IntegrationScenarioContext.cs index 4fb58d40..e27a8832 100644 --- a/src/NServiceBus.IntegrationTesting/IntegrationScenarioContext.cs +++ b/src/NServiceBus.IntegrationTesting/IntegrationScenarioContext.cs @@ -1,4 +1,5 @@ using NServiceBus.AcceptanceTesting; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; @@ -11,6 +12,7 @@ public class IntegrationScenarioContext : ScenarioContext readonly ConcurrentBag invokedHandlers = new ConcurrentBag(); readonly ConcurrentBag invokedSagas = new ConcurrentBag(); readonly ConcurrentBag outgoingMessageOperations = new ConcurrentBag(); + readonly ConcurrentDictionary createdSagaInstances = new ConcurrentDictionary(); public IEnumerable InvokedHandlers { get { return invokedHandlers; } } public IEnumerable InvokedSagas { get { return invokedSagas; } } @@ -35,6 +37,16 @@ internal SagaInvocation CaptureInvokedSaga(SagaInvocation invocation) return invocation; } + internal void RegisterSagaInstanceAsCreated(Guid sagaId, Type sagaDataType) + { + createdSagaInstances.AddOrUpdate(sagaId, sagaDataType, (id, type) => type); + } + + public bool IsSagaInstanceAvailable(Guid sagaId) + { + return createdSagaInstances.ContainsKey(sagaId); + } + public bool HandlerWasInvoked() { return InvokedHandlers.Any(invocation => invocation.HandlerType == typeof(THandler)); diff --git a/src/NServiceBus.IntegrationTesting/MessageSessionExtensions.cs b/src/NServiceBus.IntegrationTesting/MessageSessionExtensions.cs new file mode 100644 index 00000000..ddd616f5 --- /dev/null +++ b/src/NServiceBus.IntegrationTesting/MessageSessionExtensions.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace NServiceBus.IntegrationTesting +{ + public static class MessageSessionExtensions + { + public static Task CreateSagaInstance(this IMessageSession messageSession, string sagaOwnerEndpoint, Guid sagaId, TSagaData sagaData, string originator = null, string originatingMessageId = null) where TSagaData : IContainSagaData + { + sagaData.Id = sagaId; + sagaData.Originator = originator; + sagaData.OriginalMessageId = originatingMessageId; + + return messageSession.Send(sagaOwnerEndpoint, new Messages.CreateSagaInstance() + { + SagaData = sagaData + }); + } + } +} diff --git a/src/NServiceBus.IntegrationTesting/Messages/CreateSagaInstance.cs b/src/NServiceBus.IntegrationTesting/Messages/CreateSagaInstance.cs new file mode 100644 index 00000000..d94e854b --- /dev/null +++ b/src/NServiceBus.IntegrationTesting/Messages/CreateSagaInstance.cs @@ -0,0 +1,9 @@ +namespace NServiceBus.IntegrationTesting.Messages +{ + class CreateSagaInstance + { + public string CorrelationPropertyName { get; set; } + public object CorrelationPropertyValue { get; set; } + public IContainSagaData SagaData { get; set; } + } +} diff --git a/src/NServiceBus.IntegrationTesting/Messages/Handlers/CreateSagaInstanceHandler.cs b/src/NServiceBus.IntegrationTesting/Messages/Handlers/CreateSagaInstanceHandler.cs new file mode 100644 index 00000000..a1b044bf --- /dev/null +++ b/src/NServiceBus.IntegrationTesting/Messages/Handlers/CreateSagaInstanceHandler.cs @@ -0,0 +1,35 @@ +using NServiceBus.AcceptanceTesting; +using NServiceBus.Sagas; +using System.Threading.Tasks; + +namespace NServiceBus.IntegrationTesting.Messages.Handlers +{ + class CreateSagaInstanceHandler : IHandleMessages + { + readonly ISagaPersister sagaPersister; + + public CreateSagaInstanceHandler(ISagaPersister sagaPersister) + { + this.sagaPersister = sagaPersister; + } + + public async Task Handle(CreateSagaInstance message, IMessageHandlerContext context) + { + var correlationProperty = new SagaCorrelationProperty( + message.CorrelationPropertyName, + message.CorrelationPropertyValue); + + await sagaPersister.Save(message.SagaData, + correlationProperty, + context.SynchronizedStorageSession, + new Extensibility.ContextBag()) + .ConfigureAwait(false); + + await context.SendLocal(new MarkSagaInstanceAsCreated() + { + SagaId = message.SagaData.Id, + SagaDataType = message.SagaData.GetType() + }).ConfigureAwait(false); + } + } +} diff --git a/src/NServiceBus.IntegrationTesting/Messages/Handlers/MarkSagaInstanceAsCreatedHandler.cs b/src/NServiceBus.IntegrationTesting/Messages/Handlers/MarkSagaInstanceAsCreatedHandler.cs new file mode 100644 index 00000000..817196f6 --- /dev/null +++ b/src/NServiceBus.IntegrationTesting/Messages/Handlers/MarkSagaInstanceAsCreatedHandler.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace NServiceBus.IntegrationTesting.Messages.Handlers +{ + class MarkSagaInstanceAsCreatedHandler : IHandleMessages + { + readonly IntegrationScenarioContext integrationScenarioContext; + + public MarkSagaInstanceAsCreatedHandler(IntegrationScenarioContext integrationScenarioContext) + { + this.integrationScenarioContext = integrationScenarioContext; + } + + public Task Handle(MarkSagaInstanceAsCreated message, IMessageHandlerContext context) + { + integrationScenarioContext.RegisterSagaInstanceAsCreated(message.SagaId, message.SagaDataType); + + return Task.CompletedTask; + } + } +} diff --git a/src/NServiceBus.IntegrationTesting/Messages/MarkSagaInstanceAsCreated.cs b/src/NServiceBus.IntegrationTesting/Messages/MarkSagaInstanceAsCreated.cs new file mode 100644 index 00000000..e9251c2b --- /dev/null +++ b/src/NServiceBus.IntegrationTesting/Messages/MarkSagaInstanceAsCreated.cs @@ -0,0 +1,10 @@ +using System; + +namespace NServiceBus.IntegrationTesting.Messages +{ + class MarkSagaInstanceAsCreated + { + public Guid SagaId { get; set; } + public Type SagaDataType { get; set; } + } +}