public async Task Should_pass_message_and_headers_to_partition_key_extractor() { object capturedMessageInstanceFromPartionKeyExtractor = null; IReadOnlyDictionary <string, string> capturedHeadersFromPartionKeyExtractor = null; var partitionKeyExtractor = new PartitionKeyExtractor( (object msg, IReadOnlyDictionary <string, string> headers, out PartitionKey? partitionKey) => { partitionKey = null; capturedMessageInstanceFromPartionKeyExtractor = msg; capturedHeadersFromPartionKeyExtractor = headers; return(true); }); var behavior = new TransactionInformationBeforeTheLogicalOutboxBehavior(partitionKeyExtractor, new ContainerInformationExtractor()); var messageHeaders = new Dictionary <string, string> { { "HeaderKey", "HeaderValue" } }; var messageInstance = new object(); var context = new TestableIncomingLogicalMessageContext { MessageHeaders = messageHeaders, Message = new LogicalMessage(new MessageMetadata(typeof(object)), messageInstance) }; await behavior.Invoke(context, _ => Task.CompletedTask); Assert.That(capturedMessageInstanceFromPartionKeyExtractor, Is.Not.Null.And.EqualTo(messageInstance)); Assert.That(capturedHeadersFromPartionKeyExtractor, Is.Not.Null.And.EqualTo(messageHeaders)); }
public UnitOfWorkBehaviorTestsFixture() { UnitsOfWork = new List <Mock <IUnitOfWork> > { new Mock <IUnitOfWork>(), new Mock <IUnitOfWork>(), new Mock <IUnitOfWork>() }; UnitOfWorkBehavior = new UnitOfWorkBehavior(); Builder = new FakeBuilder(); Context = new TestableIncomingLogicalMessageContext { Builder = Builder }; NextTask = new Mock <Func <Task> >(); Builder.Register(UnitsOfWork.Select(u => u.Object).Concat(new[] { new NServiceBus.Features.ClientOutbox.Pipeline.UnitOfWork(null, null, null, null) }).ToArray()); NextTask.Setup(n => n()).Returns(Task.CompletedTask).Callback(() => { if (CommittedUnitsOfWork > 0) { throw new Exception("Next invoked too late"); } }); UnitsOfWork.ForEach(u => u.Setup(u2 => u2.CommitAsync(It.IsAny <Func <Task> >())).Returns <Func <Task> >(t => { CommittedUnitsOfWork++; return(t()); })); }
public override Task Invoke(IIncomingPhysicalMessageContext context, Func <IIncomingLogicalMessageContext, Task> stage) { context.PrintInstanceWithRunSpecificIfPossible(instance, writer); var logicalMessageContext = new TestableIncomingLogicalMessageContext(); logicalMessageContext.Extensions.Merge(context.Extensions); return(stage(logicalMessageContext)); }
public void Should_throw_when_there_are_no_registered_message_handlers() { var behavior = new LoadHandlersConnector(new MessageHandlerRegistry(new Conventions()), new InMemorySynchronizedStorage(), new InMemoryTransactionalSynchronizedStorageAdapter()); var context = new TestableIncomingLogicalMessageContext(); context.Extensions.Set<OutboxTransaction>(new InMemoryOutboxTransaction()); context.Extensions.Set(new TransportTransaction()); Assert.That(async () => await behavior.Invoke(context, c => TaskEx.CompletedTask), Throws.InvalidOperationException); }
public async Task ShouldProcessMessage() { var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <Messages.IEvent>()); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(); }
public void Should_throw_when_there_are_no_registered_message_handlers() { var behavior = new LoadHandlersConnector(new MessageHandlerRegistry(), new InMemorySynchronizedStorage(), new InMemoryTransactionalSynchronizedStorageAdapter()); var context = new TestableIncomingLogicalMessageContext(); context.Extensions.Set <OutboxTransaction>(new InMemoryOutboxTransaction()); context.Extensions.Set(new TransportTransaction()); Assert.That(async() => await behavior.Invoke(context, c => Task.CompletedTask), Throws.InvalidOperationException); }
public async Task When_processing_message_without_enclosed_message_type_header_it_is_addedAsync() { var behavior = new InferredMessageTypeEnricherBehavior(); var context = new TestableIncomingLogicalMessageContext(); Assert.IsFalse(context.Headers.ContainsKey(Headers.EnclosedMessageTypes)); await behavior.Invoke(context, messageContext => Task.CompletedTask); Assert.IsTrue(context.Headers.ContainsKey(Headers.EnclosedMessageTypes)); Assert.AreEqual(context.Headers[Headers.EnclosedMessageTypes], typeof(object).FullName); }
public Task IncomingLogicalMessageContext() { var context = new TestableIncomingLogicalMessageContext { Message = BuildLogicalMessage(), Headers = new Dictionary <string, string> { { "Key", "Value" } } }; return(Verify(context)); }
public async Task When_processing_message_with_enclosed_message_type_header_it_is_not_changedAsync() { var mutator = new InferredMessageTypeEnricherBehavior(); var context = new TestableIncomingLogicalMessageContext(); context.Headers.Add(Headers.EnclosedMessageTypes, typeof(string).FullName); await mutator.Invoke(context, messageContext => Task.CompletedTask); Assert.IsTrue(context.Headers.ContainsKey(Headers.EnclosedMessageTypes)); Assert.AreEqual(context.Headers[Headers.EnclosedMessageTypes], typeof(string).FullName); }
public async Task ShouldUnpackLocalDelivery() { var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.Extensions.Set(Defaults.LocalHeader, Fake <IFullMessage>()); context.UpdateMessageInstance(Fake <IFullMessage>()); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(); }
public void Below_v4_3_0_should_return_value_for_all_intents(string nsbVersion, MessageIntentEnum intent) { var correlationId = new Guid().ToString(); var lookup = new RequestResponseStateLookup(); lookup.RegisterState(correlationId, new RequestResponseStateLookup.State()); var message = new IncomingMessageFromLegacyEndpoint(nsbVersion, intent); var incomingContext = new TestableIncomingLogicalMessageContext(); incomingContext.MessageHeaders.Add(Headers.CorrelationId, correlationId); var result = incomingContext.TryRemoveResponseStateBasedOnCorrelationId(message, lookup); Assert.IsTrue(result.HasValue); }
public async Task ShouldNotAcceptIfNoResponseRequested() { var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <ICommand>()); context.MessageHeaders[Defaults.RequestResponse] = "0"; await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(); context.RepliedMessages.Should().BeEmpty(); }
public async Task Should_not_call_MutateIncoming_when_hasIncomingMessageMutators_is_false() { var behavior = new MutateIncomingMessageBehavior(hasIncomingMessageMutators: false); var context = new TestableIncomingLogicalMessageContext(); var mutator = new MutatorThatIndicatesIfItWasCalled(); context.Builder.Register<IMutateIncomingMessages>(() => mutator); await behavior.Invoke(context, ctx => TaskEx.CompletedTask); Assert.IsFalse(mutator.MutateIncomingCalled); }
public async Task Should_not_call_MutateIncoming_when_hasIncomingMessageMutators_is_false() { var behavior = new MutateIncomingMessageBehavior(hasIncomingMessageMutators: false); var context = new TestableIncomingLogicalMessageContext(); var mutator = new MutatorThatIndicatesIfItWasCalled(); context.Builder.Register <IMutateIncomingMessages>(() => mutator); await behavior.Invoke(context, ctx => TaskEx.CompletedTask); Assert.IsFalse(mutator.MutateIncomingCalled); }
public async Task ShouldReplyToCommand() { var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <ICommand>()); context.MessageHeaders[Defaults.RequestResponse] = "1"; context.Builder.Register <Action <Accept> >(A.Fake <Action <Accept> >()); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(); context.RepliedMessages.Should().NotBeEmpty(); context.RepliedMessages[0].Message.Should().BeAssignableTo <Accept>(); }
public void Below_v5_0_0_should_return_value_for_all_intents(string nsbVersion, MessageIntentEnum intent) { var correlationId = new Guid().ToString(); var lookup = new RequestResponseStateLookup(); lookup.RegisterState(correlationId, new RequestResponseStateLookup.State()); var message = new IncomingMessageFromLegacyEndpoint(nsbVersion, intent); var incomingContext = new TestableIncomingLogicalMessageContext(); incomingContext.MessageHeaders.Add(Headers.CorrelationId, correlationId); var result = incomingContext.TryRemoveResponseStateBasedOnCorrelationId(message, lookup); Assert.IsTrue(result.HasValue); }
public async Task ShouldUnpackBulkMessage() { var message = new Internal.BulkMessage { Messages = Many <IFullMessage>() }; var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(message); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(3, Times.Exactly); }
public void Should_throw_friendly_exception_when_IMutateIncomingMessages_MutateIncoming_returns_null() { var behavior = new MutateIncomingMessageBehavior(hasIncomingMessageMutators: true); var logicalMessage = new LogicalMessage(new MessageMetadata(typeof(TestMessage)), new TestMessage()); var context = new TestableIncomingLogicalMessageContext { Message = logicalMessage }; context.Builder.Register<IMutateIncomingMessages>(() => new MutateIncomingMessagesReturnsNull()); Assert.That(async () => await behavior.Invoke(context, ctx => TaskEx.CompletedTask), Throws.Exception.With.Message.EqualTo("Return a Task or mark the method as async.")); }
public async Task Shares_state_with_pipeline_context() { var pipelineContext = new TestableIncomingLogicalMessageContext(); var uniformSession = new TestableUniformSession(pipelineContext); var behavior = new SendingBehavior(uniformSession); await behavior.Invoke(pipelineContext, () => Task.CompletedTask); Assert.AreEqual(2, uniformSession.PublishedMessages.Length); Assert.AreEqual(2, uniformSession.SentMessages.Length); Assert.AreEqual(2, pipelineContext.PublishedMessages.Length); Assert.AreEqual(2, pipelineContext.SentMessages.Length); Assert.AreEqual("testValue", pipelineContext.Headers["testHeader"]); }
public void Should_throw_friendly_exception_when_IMutateIncomingMessages_MutateIncoming_returns_null() { var behavior = new MutateIncomingMessageBehavior(); var logicalMessage = new LogicalMessage(new MessageMetadata(typeof(TestMessage)), new TestMessage()); var context = new TestableIncomingLogicalMessageContext { Message = logicalMessage }; context.Builder.Register <IMutateIncomingMessages>(() => new MutateIncomingMessagesReturnsNull()); Assert.That(async() => await behavior.Invoke(context, ctx => TaskEx.CompletedTask), Throws.Exception.With.Message.EqualTo("Return a Task or mark the method as async.")); }
public void SetUp() { logicalContext = new TestableIncomingLogicalMessageContext(); scheduler = new DefaultScheduler(); behavior = new ScheduledTaskHandlingBehavior(scheduler); var task = new TaskDefinition { Every = TimeSpan.FromSeconds(5), Task = c => Task.CompletedTask }; taskId = task.Id; scheduler.Schedule(task); }
public async Task Should_clear_added_pending_operations_and_restore_ones_from_outbox_record() { var messageId = Guid.NewGuid().ToString(); var transportOperations = new[] { new TransportOperation( messageId: "42", properties: new DispatchProperties { { "Destination", "somewhere" } }, body: Array.Empty <byte>(), headers: new Dictionary <string, string>()), }; var fakeCosmosClient = new FakeCosmosClient(new FakeContainer { ReadItemStreamOutboxRecord = (id, key) => new OutboxRecord { Dispatched = false, Id = messageId, TransportOperations = transportOperations.Select(op => new StorageTransportOperation(op)) .ToArray() } }); var containerHolderHolderResolver = new ContainerHolderResolver(new FakeProvider(fakeCosmosClient), new ContainerInformation("fakeContainer", new PartitionKeyPath("")), "fakeDatabase"); var behavior = new OutboxBehavior(containerHolderHolderResolver, new JsonSerializer()); var testableContext = new TestableIncomingLogicalMessageContext(); testableContext.Extensions.Set(new PartitionKey("")); testableContext.Extensions.Set(new SetAsDispatchedHolder()); testableContext.Extensions.Set <IOutboxTransaction>(new CosmosOutboxTransaction(containerHolderHolderResolver, testableContext.Extensions)); var pendingTransportOperations = new PendingTransportOperations(); pendingTransportOperations.Add(new Transport.TransportOperation(new OutgoingMessage(null, null, null), null)); testableContext.Extensions.Set(pendingTransportOperations); await behavior.Invoke(testableContext, c => Task.CompletedTask); Assert.IsTrue(pendingTransportOperations.HasOperations, "Should have exactly one operation added found on the outbox record"); Assert.AreEqual("42", pendingTransportOperations.Operations.ElementAt(0).Message.MessageId, "Should have exactly one operation added found on the outbox record"); }
public async Task Should_invoke_all_explicit_mutators() { var mutator = new MutatorThatIndicatesIfItWasCalled(); var otherMutator = new MutatorThatIndicatesIfItWasCalled(); var behavior = new MutateIncomingMessageBehavior(new HashSet <IMutateIncomingMessages> { mutator, otherMutator }); var context = new TestableIncomingLogicalMessageContext(); await behavior.Invoke(context, ctx => TaskEx.CompletedTask); Assert.True(mutator.MutateIncomingCalled); Assert.True(otherMutator.MutateIncomingCalled); }
public async Task Should_not_call_MutateIncoming_when_hasIncomingMessageMutators_is_false() { var behavior = new MutateIncomingMessageBehavior(new HashSet <IMutateIncomingMessages>()); var context = new TestableIncomingLogicalMessageContext(); await behavior.Invoke(context, ctx => Task.CompletedTask); var mutator = new MutatorThatIndicatesIfItWasCalled(); context.Services.AddTransient <IMutateIncomingMessages>(sp => mutator); await behavior.Invoke(context, ctx => Task.CompletedTask); Assert.IsFalse(mutator.MutateIncomingCalled); }
public async Task ShouldRejectCommand() { var next = A.Fake <Func <Task> >(); A.CallTo(() => next()).Throws <BusinessException>(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <ICommand>()); context.MessageHeaders[Defaults.RequestResponse] = "1"; context.Builder.Register <Action <BusinessException, Reject> >(A.Fake <Action <BusinessException, Reject> >()); var e = await Record.ExceptionAsync(() => Sut.Invoke(context, next)).ConfigureAwait(false); e.Should().BeOfType <BusinessException>(); context.RepliedMessages.Should().NotBeEmpty(); context.RepliedMessages[0].Message.Should().BeAssignableTo <Reject>(); }
public async Task ShouldMutateMessage() { var mutator = new FakeMutator(); A.CallTo(() => Configuration.Settings.Container.Resolve(A <Type> .Ignored)).Returns(mutator); MutationManager.RegisterMutator("test", typeof(FakeMutator)); var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <Messages.IEvent>()); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(); mutator.MutatedIncoming.Should().BeTrue(); }
public async Task Should_not_set_container_information_when_container_information_extractor_returns_false() { var extractor = new ContainerInformationExtractor( (object msg, IReadOnlyDictionary <string, string> headers, out ContainerInformation? container) => { container = null; return(false); }); var behavior = new TransactionInformationBeforeTheLogicalOutboxBehavior(new CosmosDB.PartitionKeyExtractor(), extractor); var context = new TestableIncomingLogicalMessageContext(); await behavior.Invoke(context, _ => Task.CompletedTask); Assert.That(context.Extensions.TryGet <ContainerInformation>(out _), Is.False); }
public async Task ShouldNotQueueRetryOnBusinessException() { var retrier = A.Fake <Internal.DelayedRetry>(); Inject(retrier); var next = A.Fake <Func <Task> >(); A.CallTo(() => next()).Throws <BusinessException>(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <Messages.IEvent>()); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => retrier.QueueRetry(A <IFullMessage> .Ignored, A <TimeSpan> .Ignored)).MustNotHaveHappened(); A.CallTo(() => next()).MustHaveHappened(); }
public async Task ShouldAddRetryHeader() { var next = A.Fake <Func <Task> >(); A.CallTo(() => next()).Throws <Exception>(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <Messages.IEvent>()); await Sut.Invoke(context, next).ConfigureAwait(false); context.Extensions.Get <int>(Defaults.Retries).Should().Be(0); await Sut.Invoke(context, next).ConfigureAwait(false); context.Extensions.Get <int>(Defaults.Retries).Should().Be(1); }
public async Task ShouldUnpackBulkHeader() { var message = Fake <IFullMessage>(); A.CallTo(() => message.Headers).Returns(new Dictionary <string, string> { [Defaults.ChannelKey] = "test" }); Inject(message); var next = A.Fake <Func <Task> >(); var context = new TestableIncomingLogicalMessageContext(); context.UpdateMessageInstance(Fake <int>()); context.Extensions.Set(Defaults.BulkHeader, Many <IFullMessage>()); await Sut.Invoke(context, next).ConfigureAwait(false); A.CallTo(() => next()).MustHaveHappened(3, Times.Exactly); }
public async Task Should_set_partition_key_when_partition_key_extractor_returns_true() { var partitionKeyExtractor = new PartitionKeyExtractor( (object msg, IReadOnlyDictionary <string, string> headers, out PartitionKey? key) => { key = new PartitionKey(true); return(true); }); var behavior = new TransactionInformationBeforeTheLogicalOutboxBehavior(partitionKeyExtractor, new ContainerInformationExtractor()); var context = new TestableIncomingLogicalMessageContext(); await behavior.Invoke(context, _ => Task.CompletedTask); Assert.That(context.Extensions.TryGet <PartitionKey>(out var partitionKey), Is.True); Assert.AreEqual(new PartitionKey(true), partitionKey); }
public async Task Should_set_container_when_container_information_extractor_returns_true() { var extractor = new ContainerInformationExtractor( (object msg, IReadOnlyDictionary <string, string> headers, out ContainerInformation? container) => { container = new ContainerInformation("containerName", new PartitionKeyPath("/deep/down")); return(true); }); var behavior = new TransactionInformationBeforeTheLogicalOutboxBehavior(new PartitionKeyExtractor(), extractor); var context = new TestableIncomingLogicalMessageContext(); await behavior.Invoke(context, _ => Task.CompletedTask); Assert.That(context.Extensions.TryGet <ContainerInformation>(out var containerInformation), Is.True); Assert.AreEqual(new ContainerInformation("containerName", new PartitionKeyPath("/deep/down")), containerInformation); }
public async Task Should_invoke_both_explicit_and_container_provided_mutators() { var explicitMutator = new MutatorThatIndicatesIfItWasCalled(); var containerMutator = new MutatorThatIndicatesIfItWasCalled(); var behavior = new MutateIncomingMessageBehavior(new HashSet <IMutateIncomingMessages> { explicitMutator }); var context = new TestableIncomingLogicalMessageContext(); context.Builder.Register <IMutateIncomingMessages>(() => containerMutator); await behavior.Invoke(context, ctx => TaskEx.CompletedTask); Assert.True(explicitMutator.MutateIncomingCalled); Assert.True(containerMutator.MutateIncomingCalled); }
public async Task Should_fire_activity_start_stop_when_listener_attached() { var diagnosticListener = new DiagnosticListener("DummySource"); var context = new TestableIncomingLogicalMessageContext(); var processedFired = false; diagnosticListener.Subscribe(new CallbackDiagnosticListener(pair => { if (pair.Key == $"{ActivityNames.IncomingLogicalMessage}.Processed") { processedFired = true; } })); var behavior = new IncomingLogicalMessageDiagnostics(diagnosticListener); await behavior.Invoke(context, () => Task.CompletedTask); processedFired.ShouldBeTrue(); }
public void SetupTests() { behavior = new InvokeSagaNotFoundBehavior(); incomingContext = new TestableIncomingLogicalMessageContext(); }