public async Task should_persist_messages_in_order() { var firstPeer = new PeerId("Abc.Testing.Target"); var secondPeer = new PeerId("Abc.Testing.OtherTarget"); _peerStateRepository.Add(new PeerState(firstPeer, 0, SystemDateTime.UtcNow.Date.Ticks)); _peerStateRepository.Add(new PeerState(secondPeer, 0, SystemDateTime.UtcNow.Date.Ticks)); using (MessageId.PauseIdGeneration()) using (SystemDateTime.PauseTime()) { var expectedTransportMessages = Enumerable.Range(1, 100).Select(CreateTestTransportMessage).ToList(); var messages = expectedTransportMessages.SelectMany(x => { var transportMessageBytes = Serialization.Serializer.Serialize(x).ToArray(); return(new[] { MatcherEntry.Message(firstPeer, x.Id, x.MessageTypeId, transportMessageBytes), MatcherEntry.Message(secondPeer, x.Id, x.MessageTypeId, transportMessageBytes), }); }) .ToList(); await _storage.Write(messages); _peerStateRepository[firstPeer].NonAckedMessageCount.ShouldEqual(100); _peerStateRepository[secondPeer].NonAckedMessageCount.ShouldEqual(100); var readerForFirstPeer = (CqlMessageReader)_storage.CreateMessageReader(firstPeer); readerForFirstPeer.GetUnackedMessages().ToList().ShouldEqualDeeply(expectedTransportMessages); var readerForSecondPeer = (CqlMessageReader)_storage.CreateMessageReader(secondPeer); readerForSecondPeer.GetUnackedMessages().ToList().ShouldEqualDeeply(expectedTransportMessages); } }
public void should_raise_PingMissed_before_a_peer_is_marked_as_timed_out() { SetupPeerRepository(_persistentAlivePeer, _transientAlivePeer0); SetupPeerResponse(_transientAlivePeer0.PeerId, true, true); SetupPeerResponse(_persistentAlivePeer.PeerId, false, false); using (SystemDateTime.PauseTime()) { var missedPings = new List <PeerEvent>(); _detector.PingTimeout += (peer, timestamp) => missedPings.Add(new PeerEvent(peer, timestamp)); var startTime = SystemDateTime.UtcNow; _detector.DetectDeadPeers(); SystemDateTime.Set(startTime.Add(_pingInterval - 1.Second())); _detector.DetectDeadPeers(); missedPings.Count.ShouldEqual(0); SystemDateTime.Set(startTime.Add(_pingInterval + 1.Second())); _detector.DetectDeadPeers(); missedPings.Count.ShouldEqual(1); missedPings.First().PeerId.ShouldEqual(_persistentAlivePeer.PeerId); SystemDateTime.Set(startTime.Add(_pingInterval + _pingInterval + 1.Second())); _detector.DetectDeadPeers(); missedPings.Count.ShouldEqual(2); missedPings.All(evt => evt.PeerId == _persistentAlivePeer.PeerId).ShouldBeTrue(); } }
public void should_timeout_if_any_debug_service_does_not_respond_in_time() { SetupPeerRepository(_debugPersistentAlivePeer, _debugTransientAlivePeer); SetupPeerResponse(_debugPersistentAlivePeer.PeerId, false, false); SetupPeerResponse(_debugTransientAlivePeer.PeerId, false, false); using (SystemDateTime.PauseTime()) { var startTime = SystemDateTime.UtcNow; var firstPingTimestampUtc = startTime; _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_debugPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_debugPeerTimeout + 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly( new UnregisterPeerCommand(_debugTransientAlivePeer.Peer, firstPingTimestampUtc), new UnregisterPeerCommand(_debugPersistentAlivePeer.Peer, firstPingTimestampUtc) ); } }
public void should_not_decommission_directory_peer() { SetupPeerRepository(_directoryPeer, _transientAlivePeer0); SetupPeerResponse(_transientAlivePeer0.PeerId, false, false); SetupPeerResponse(_directoryPeer.PeerId, false, false); using (SystemDateTime.PauseTime()) { var startTime = SystemDateTime.UtcNow; var firstPingTimestampUtc = startTime; _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout + 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new UnregisterPeerCommand(_transientAlivePeer0.Peer, firstPingTimestampUtc)); } }
public void should_not_decommission_the_persistence() { SetupPeerRepository(_persistencePeer); SetupPeerResponse(_persistencePeer.PeerId, false, false); using (SystemDateTime.PauseTime()) { var startTime = SystemDateTime.UtcNow; var persistenceDownDetectedCount = 0; _detector.PersistenceDownDetected += () => persistenceDownDetectedCount++; _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand()); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout + 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); persistenceDownDetectedCount.ShouldEqual(1); } }
public void should_timeout_if_a_persistent_service_does_not_respond_in_time() { SetupPeerRepository(_persistentAlivePeer, _transientAlivePeer0); SetupPeerResponse(_transientAlivePeer0.PeerId, true, true); SetupPeerResponse(_persistentAlivePeer.PeerId, false, false); using (SystemDateTime.PauseTime()) { var startTime = SystemDateTime.UtcNow; var firstPingTimestampUtc = startTime; _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); var retryTimestamp = startTime.AddSeconds(_persistentPeerTimeout - 1); SystemDateTime.Set(retryTimestamp); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_persistentPeerTimeout + 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new MarkPeerAsNotRespondingCommand(_persistentAlivePeer.Peer.Id, firstPingTimestampUtc)); } }
public void should_mark_as_not_responding_if_a_transient_peer_in_the_whitelist_does_not_respond_in_time(string peerNotToDecommission) { _peersNotToDecommission = new[] { peerNotToDecommission }; SetupPeerRepository(_transientAlivePeer0); SetupPeerResponse(_transientAlivePeer0.PeerId, false, false); using (SystemDateTime.PauseTime()) { var startTime = SystemDateTime.UtcNow; var firstPingTimestampUtc = startTime; _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout + 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new MarkPeerAsNotRespondingCommand(_transientAlivePeer0.Peer.Id, firstPingTimestampUtc)); } }
public void should_not_timeout_if_a_persistent_service_responds_to_the_second_ping() { SetupPeerRepository(_persistentAlivePeer, _transientAlivePeer0); SetupPeerResponse(_transientAlivePeer0.PeerId, true, true); SetupPeerResponse(_persistentAlivePeer.PeerId, false, true); using (SystemDateTime.PauseTime()) { var startTime = SystemDateTime.UtcNow; _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_transientPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_persistentPeerTimeout - 1)); _detector.DetectDeadPeers(); _bus.ExpectExactly(new PingPeerCommand(), new PingPeerCommand()); _bus.ClearMessages(); SystemDateTime.Set(startTime.AddSeconds(_persistentPeerTimeout + 1)); _detector.DetectDeadPeers(); _bus.ExpectNothing();; } }
public async Task should_write_message_entry_fields_to_cassandra() { using (SystemDateTime.PauseTime()) { var messageBytes = new byte[512]; new Random().NextBytes(messageBytes); var messageId = MessageId.NextId(); var peerId = "Abc.Peer.0"; await _storage.Write(new List <MatcherEntry> { MatcherEntry.Message(new PeerId(peerId), messageId, MessageTypeId.PersistenceStopping, messageBytes) }); var retrievedMessage = DataContext.PersistentMessages.Execute().ExpectedSingle(); retrievedMessage.TransportMessage.ShouldBeEquivalentTo(messageBytes, true); retrievedMessage.BucketId.ShouldEqual(GetBucketIdFromMessageId(messageId)); retrievedMessage.IsAcked.ShouldBeFalse(); retrievedMessage.PeerId.ShouldEqual(peerId); retrievedMessage.UniqueTimestampInTicks.ShouldEqual(messageId.GetDateTime().Ticks); var writeTimeRow = DataContext.Session.Execute("SELECT WRITETIME(\"IsAcked\") FROM \"PersistentMessage\";").ExpectedSingle(); writeTimeRow.GetValue <long>(0).ShouldEqual(ToUnixMicroSeconds(messageId.GetDateTime())); var peerState = DataContext.PeerStates.Execute().ExpectedSingle(); peerState.NonAckedMessageCount.ShouldEqual(1); peerState.PeerId.ShouldEqual(peerId); peerState.OldestNonAckedMessageTimestamp.ShouldEqual(messageId.GetDateTime().Ticks - PeerState.MessagesTimeToLive.Ticks); } }
public void should_return_utc_timestamps() { using (SystemDateTime.PauseTime()) { new UniqueTimestampProvider().NextUtcTimestamp().ShouldApproximateDateTime(SystemDateTime.UtcNow); } }
public async Task should_remove_peer_subscriptions_for_a_type_if_there_are_no_binding_keys() { using (SystemDateTime.PauseTime()) { var subscriptionsForTypes = new[] { new SubscriptionsForType(MessageUtil.GetTypeId(typeof(int))), new SubscriptionsForType(MessageUtil.GetTypeId(typeof(double)), BindingKey.Empty) }; await _peerDirectory.RegisterAsync(_bus, _self, Enumerable.Empty <Subscription>()); _bus.ClearMessages(); SubscriptionsForType[] addedSubscriptions = null; MessageTypeId[] removedMessageTypeIds = null; _repositoryMock.Setup(repo => repo.AddDynamicSubscriptionsForTypes(_self.Id, SystemDateTime.UtcNow, It.IsAny <SubscriptionsForType[]>())) .Callback((PeerId peerId, DateTime timestampUtc, SubscriptionsForType[] subs) => addedSubscriptions = subs); _repositoryMock.Setup(repo => repo.RemoveDynamicSubscriptionsForTypes(_self.Id, SystemDateTime.UtcNow, It.IsAny <MessageTypeId[]>())) .Callback((PeerId peerId, DateTime timestampUtc, MessageTypeId[] ids) => removedMessageTypeIds = ids); await _peerDirectory.UpdateSubscriptionsAsync(_bus, subscriptionsForTypes); var addedSubscription = addedSubscriptions.ExpectedSingle(); addedSubscription.ShouldHaveSamePropertiesAs(new SubscriptionsForType(MessageUtil.GetTypeId(typeof(double)), BindingKey.Empty)); var removedMessageTypeId = removedMessageTypeIds.ExpectedSingle(); removedMessageTypeId.ShouldHaveSamePropertiesAs(MessageUtil.GetTypeId(typeof(int))); _bus.ExpectExactly(new PeerSubscriptionsForTypesUpdated(_self.Id, SystemDateTime.UtcNow, subscriptionsForTypes)); } }
public void should_send_MessageProcessingFailed_if_unable_to_deserialize_message() { SetupPeersHandlingMessage <MessageProcessingFailed>(_peerUp); _bus.Start(); var command = new FakeCommand(123); _messageSerializer.AddSerializationExceptionFor(command.TypeId(), "Serialization error"); using (SystemDateTime.PauseTime()) using (MessageId.PauseIdGeneration()) { var transportMessage = command.ToTransportMessage(); var messageProcessingFailedBytes = new MessageProcessingFailed(null, null, null, DateTime.UtcNow, null).ToTransportMessage().Content; _messageSerializer.AddSerializationFuncFor <MessageProcessingFailed>(x => { x.FailingMessage.ShouldEqual(transportMessage); x.ExceptionUtcTime.ShouldEqual(SystemDateTime.UtcNow); x.ExceptionMessage.ShouldContain("Unable to deserialize message"); return(messageProcessingFailedBytes); }); _transport.RaiseMessageReceived(transportMessage); var processingFailedTransportMessage = new TransportMessage(MessageUtil.TypeId <MessageProcessingFailed>(), messageProcessingFailedBytes, _self); _transport.ExpectExactly(new TransportMessageSent(processingFailedTransportMessage, _peerUp)); } }
public void should_save_entries_with_different_timestamps_in_different_batches() { var persistedEntries = new List <MatcherEntry>(); _storeBatchFunc = entries => persistedEntries.AddRange(entries); _delay = 5.Seconds(); _batchSize = 10; using (SystemDateTime.PauseTime()) { // messages for batch 1 _matcher.EnqueueMessage(_peerId, MessageId.NextId(), new MessageTypeId("Abc.X"), new byte[0]); _matcher.EnqueueMessage(_peerId, MessageId.NextId(), new MessageTypeId("Abc.X"), new byte[0]); SystemDateTime.Set(utcNow: SystemDateTime.UtcNow.Add(4.Seconds())); // message for batch 2 _matcher.EnqueueMessage(_peerId, MessageId.NextId(), new MessageTypeId("Abc.X"), new byte[0]); SystemDateTime.Set(utcNow: SystemDateTime.UtcNow.Add(3.Seconds())); _matcher.Start(); Wait.Until(() => persistedEntries.Count == 2, 500.Milliseconds()); SystemDateTime.Set(utcNow: SystemDateTime.UtcNow.Add(2.Seconds())); Wait.Until(() => persistedEntries.Count == 3, 500.Milliseconds()); } }
public void should_persist_message_and_ack(int batchSize) { var persistedEntries = new List <MatcherEntry>(); _storeBatchFunc = persistedEntries.AddRange; _batchSize = batchSize; using (SystemDateTime.PauseTime()) { _matcher.Start(); var messageId = MessageId.NextId(); _matcher.EnqueueMessage(_peerId, messageId, new MessageTypeId("Abc.X"), new byte[0]); var signal = new AutoResetEvent(false); _matcher.EnqueueWaitHandle(signal); signal.WaitOne(50000).ShouldBeTrue(); _matcher.EnqueueAck(_peerId, messageId); _matcher.EnqueueWaitHandle(signal); signal.WaitOne(50000).ShouldBeTrue(); persistedEntries.Count.ShouldEqual(2); } }
public void should_not_ack_message_with_other_peer_id() { _batchSize = 100; _delay = 2.Seconds(); var signal = new ManualResetEventSlim(); var persistedEntries = new List <MatcherEntry>(); _storeBatchFunc = entries => { persistedEntries.AddRange(entries); signal.Set(); }; using (SystemDateTime.PauseTime()) { _matcher.Start(); var messageId = MessageId.NextId(); _matcher.EnqueueMessage(_peerId, messageId, new MessageTypeId("X"), new byte[0]); _matcher.EnqueueMessage(_otherPeerId, messageId, new MessageTypeId("X"), new byte[0]); _matcher.EnqueueAck(_otherPeerId, messageId); SystemDateTime.Set(utcNow: SystemDateTime.UtcNow.Add(_delay.Value)); var persistCalled = signal.Wait(1.Second()); persistCalled.ShouldBeTrue(); var persistedEntry = persistedEntries.ExpectedSingle(); persistedEntry.PeerId.ShouldEqual(_peerId); } }
public void should_convert_message_id_to_DateTime() { MessageId.ResetLastTimestamp(); using (SystemDateTime.PauseTime()) { var id = MessageId.NextId(); var date = id.GetDateTime(); date.ShouldEqual(SystemDateTime.UtcNow); } }
public void should_convert_message_id_to_DateTime() { Thread.Sleep(1); // To ensure that noone called NextId() in this millisecond, because MessageId has a static state and would increment its value using (SystemDateTime.PauseTime()) { var id = MessageId.NextId(); var date = id.GetDateTime(); date.ShouldEqual(SystemDateTime.UtcNow); } }
public async Task should_handle_null_bindingkeys_array_when_removing_subscriptions() { using (SystemDateTime.PauseTime()) { var subscriptionsForTypes = new[] { new SubscriptionsForType(MessageUtil.GetTypeId(typeof(int)), null) }; await _peerDirectory.RegisterAsync(_bus, _self, new[] { Subscription.Any <FakeCommand>() }); await _peerDirectory.UpdateSubscriptionsAsync(_bus, subscriptionsForTypes); _repositoryMock.Verify(repo => repo.RemoveDynamicSubscriptionsForTypes(_self.Id, SystemDateTime.UtcNow, new[] { MessageUtil.GetTypeId(typeof(int)) })); } }
public async Task register_persist_state_and_advertise() { using (SystemDateTime.PauseTime()) using (SystemDateTime.Set(SystemDateTime.Now)) { var peerDescriptor = _self.ToPeerDescriptor(false, typeof(FakeCommand)); await _peerDirectory.RegisterAsync(_bus, peerDescriptor.Peer, peerDescriptor.Subscriptions); _bus.ExpectExactly(new PeerStarted(peerDescriptor)); _repositoryMock.Verify(x => x.AddOrUpdatePeer(It.Is <PeerDescriptor>(descriptor => peerDescriptor.DeepCompare(descriptor)))); } }
public void should_take_utc_now_timestamp_as_oldest_non_acked_message_when_no_messages_are_acked() { using (SystemDateTime.PauseTime()) { var peerId = new PeerId("PeerId"); var now = SystemDateTime.UtcNow; _peerStateRepo.Add(new PeerState(peerId, 0, now.AddMilliseconds(2).Ticks)); _oldestMessageUpdater.DoPeriodicAction(); _peerStateRepo[peerId].OldestNonAckedMessageTimestampInTicks.ShouldEqual(now.Ticks); } }
public void should_reset_time_when_paused() { using (SystemDateTime.PauseTime()) { var now = SystemDateTime.UtcNow; Thread.Sleep(50.Milliseconds()); SystemDateTime.Reset(); Thread.Sleep(50.Milliseconds()); SystemDateTime.UtcNow.ShouldBeGreaterThan(now); SystemDateTime.Now.ShouldBeGreaterThan(now.ToLocalTime()); } }
public void should_not_register_existing_peer() { var subscriptions = TestDataBuilder.CreateSubscriptions <FakeCommand>(); _configurationMock.SetupGet(x => x.IsPersistent).Returns(true); _bus.AddHandler <RegisterPeerCommand>(x => throw new DomainException(DirectoryErrorCodes.PeerAlreadyExists, "Peer already exists")); using (SystemDateTime.PauseTime()) { Assert.Throws <AggregateException>(() => _directory.RegisterAsync(_bus, _self, subscriptions).Wait(20.Seconds())) .InnerException.ShouldBe <TimeoutException>(); } }
public async Task should_delete_peer_from_cassandra_when_removed() { using (SystemDateTime.PauseTime()) { _peerStateRepository.UpdateNonAckMessageCount(new PeerId("PeerId"), 10); await _peerStateRepository.Save(); DataContext.PeerStates.Execute().ShouldNotBeEmpty(); await _peerStateRepository.RemovePeer(new PeerId("PeerId")); DataContext.PeerStates.Execute().ShouldBeEmpty(); } }
public void should_not_send_a_MessageProcessingFailed_on_domain_exception_with_local_processing() { using (SystemDateTime.PauseTime()) using (MessageId.PauseIdGeneration()) { var command = new FakeCommand(123); SetupDispatch(command, error: new DomainException(123, "Exception message")); SetupPeersHandlingMessage <FakeCommand>(_self); _bus.Send(command); _transport.ExpectNothing(); } }
public async Task should_publish_event_when_modifying_subscriptions() { using (SystemDateTime.PauseTime()) { var subscriptionsForTypes = new[] { new SubscriptionsForType(MessageUtil.GetTypeId(typeof(int)), BindingKey.Empty) }; await _peerDirectory.RegisterAsync(_bus, _self, new[] { Subscription.Any <FakeCommand>() }); _bus.ClearMessages(); await _peerDirectory.UpdateSubscriptionsAsync(_bus, subscriptionsForTypes); _bus.ExpectExactly(new PeerSubscriptionsForTypesUpdated(_self.Id, SystemDateTime.UtcNow, subscriptionsForTypes)); } }
public void should_persist_message() { using (SystemDateTime.PauseTime()) { var transportMessage = new FakeCommand(42).ToTransportMessage(); var peerId = new PeerId("Abc.Testing.Target"); var command = new PersistMessageCommand(transportMessage, new[] { peerId }); Handler.Handle(command); Wait.Until(() => _inMemoryMessageMatcher.CassandraInsertCount == 1, 2.Seconds()); _storageMock.Verify(x => x.Write(It.IsAny <IList <MatcherEntry> >()), Times.Once); } }
public async Task should_take_utc_now_timestamp_as_oldest_non_acked_message_when_no_messages_are_acked() { using (SystemDateTime.PauseTime()) { var peerId = new PeerId("PeerId"); var now = SystemDateTime.UtcNow; var peerState = new PeerState(peerId, 0, now.AddDays(-2).Ticks); InsertPeerState(peerState); await _storage.UpdateNewOldestMessageTimestamp(peerState); GetPeerState(peerId).OldestNonAckedMessageTimestampInTicks.ShouldEqual(now.Ticks - _expectedOldestNonAckedMessageTimestampSafetyOffset); } }
public async Task should_save_state_to_cassandra() { using (SystemDateTime.PauseTime()) { _peerStateRepository.UpdateNonAckMessageCount(new PeerId("PeerId"), 10); await _peerStateRepository.Save(); var oldestNonAckedMessageTimestampCaptured = SystemDateTime.UtcNow - CqlStorage.PersistentMessagesTimeToLive; var cassandraState = DataContext.PeerStates.Execute().ExpectedSingle(); cassandraState.PeerId.ShouldEqual("PeerId"); cassandraState.NonAckedMessageCount.ShouldEqual(10); cassandraState.OldestNonAckedMessageTimestamp.ShouldEqual(oldestNonAckedMessageTimestampCaptured.Ticks); } }
public void should_pause_time() { using (SystemDateTime.PauseTime()) { var utcNow = SystemDateTime.UtcNow; Thread.Sleep(50.Milliseconds()); utcNow.ShouldEqual(SystemDateTime.UtcNow); utcNow.ShouldEqual(SystemDateTime.UtcNow); utcNow.ShouldEqual(SystemDateTime.UtcNow); var now = SystemDateTime.Now; Thread.Sleep(50.Milliseconds()); now.ShouldEqual(SystemDateTime.Now); now.ShouldEqual(SystemDateTime.Now); now.ShouldEqual(SystemDateTime.Now); } }
public async Task unregister_should_persist_state_and_advertise() { using (SystemDateTime.PauseTime()) using (SystemDateTime.Set(SystemDateTime.Now)) { var peerDescriptor = _self.ToPeerDescriptor(true, typeof(FakeCommand)); _repositoryMock.Setup(repo => repo.Get(It.Is <PeerId>(id => peerDescriptor.Peer.Id.Equals(id)))).Returns(peerDescriptor); await _peerDirectory.RegisterAsync(_bus, peerDescriptor.Peer, peerDescriptor.Subscriptions); await _peerDirectory.UnregisterAsync(_bus); _bus.Expect(new PeerStopped(peerDescriptor.Peer)); _repositoryMock.Verify(repo => repo.Get(It.Is <PeerId>(id => peerDescriptor.Peer.Id.Equals(id)))); _repositoryMock.Verify(repo => repo.AddOrUpdatePeer(It.Is <PeerDescriptor>(descriptor => peerDescriptor.DeepCompare(descriptor)))); } }