public void Node_issues_while_building_transfer_amount_transaction() { //ARRANGE var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Node_issues_while_building_transfer_amount_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransferAmountTransactionBuilder.Setup(x => x.BuildTransferAmountAsync(It.IsAny <BuildTransferAmountTransactionRequest>())) .ThrowsAsync( new TransactionBuildingException( TransactionBuildingError.RetryLater, "Node is too busy")); }); //ACT && ASSERT Assert.ThrowsAsync <TransactionBuildingWebApiException>(async() => { var transfers = new[] { new Transfer( new Asset("asset"), UMoney.Create(1000000000, 4), new Address("x1"), new Address("x2")), }; var request = new BuildTransferAmountTransactionRequest(transfers, Array.Empty <Fee>()); await client.BuildTransferAmountTransactionAsync(request); }); }
private static async Task <object> BuildInvalidTransactionAsync(ITransactionsExecutorApi client) { Console.WriteLine("Building the invalid transaction..."); return(await client.BuildTransferAmountTransactionAsync ( new BuildTransferAmountTransactionRequest ( new[] { new Transfer ( new Asset("STEEM"), UMoney.Create(100, 3), "Test:c021d892538b4a7a8520ae46f368c00f", "Test:0662c0c7b9954373a5803fab41d97774" ), new Transfer ( new Asset("STEEM"), UMoney.Create(50, 3), "Test:c021d892538b4a7a8520ae46f368c00f", "Test:0662c0c7b9954373a5803fab41d97774" ) }, new [] { new Fee(new Asset("STEEM"), UMoney.Create(0.001m, 3)) } ) )); }
public void Bad_request_while_estimating_transfer_amount_transaction() { //ARRANGE var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Bad_request_while_estimating_transfer_amount_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransactionEstimator.Setup(x => x.EstimateTransferAmountAsync(It.IsAny <EstimateTransferAmountTransactionRequest>())) .ThrowsAsync(new RequestValidationException("Not VALID")); }); //ACT && ASSERT Assert.ThrowsAsync <BadRequestWebApiException>(async() => { var transfers = new[] { new Transfer( new Asset("asset"), UMoney.Create(1000000000, 4), new Address("x1"), new Address("x2")), }; var request = new EstimateTransferAmountTransactionRequest(transfers); await client.EstimateTransferAmountTransactionAsync(request); }); }
public void Money_Should_Be_Serializable_To_Json() { JsonConvert .SerializeObject(UMoney.Create(10, 5)) .Should() .Be("\"10.00000\""); }
public async Task Build_transfer_amount_transaction() { //ARRANGE string transactionResponse = "transactionResponse"; var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Build_transfer_amount_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransferAmountTransactionBuilder.Setup(x => x.BuildTransferAmountAsync(It.IsAny <BuildTransferAmountTransactionRequest>())) .ReturnsAsync(new BuildTransactionResponse(Base64String.Encode(transactionResponse))); }); //ACT var transfers = new[] { new Transfer( new Asset("asset"), UMoney.Create(1000000000, 4), new Address("x1"), new Address("x2")), }; var request = new BuildTransferAmountTransactionRequest(transfers, Array.Empty <Fee>()); var result = await client.BuildTransferAmountTransactionAsync(request); //ASSERT Assert.True(result != null); Assert.True(result.TransactionContext.DecodeToString() == transactionResponse); }
public void Money_Should_Be_Deserializable_From_Json() { JsonConvert .DeserializeObject <UMoney>("\"10.00000\"") .Should() .Be(UMoney.Create(10, 5)); }
public void Test_that_coins_to_receive_should_be_numbers_in_a_row_starting_from_zero(string coinsToReceiveNumbers, bool shouldThrow) { var coinToSpend = new CoinToSpend ( new CoinId("1", 1), new Asset("KIN"), UMoney.Create(100, 3), "A" ); var coinsToReceive = coinsToReceiveNumbers .Split(',') .Select(x => new CoinToReceive ( int.Parse(x), new Asset("KIN"), UMoney.Create(1, 3), "B" )) .ToArray(); if (shouldThrow) { Assert.Throws <RequestValidationException>(() => TransactionCoinsValidator.Validate(new[] { coinToSpend }, coinsToReceive)); } else { Assert.DoesNotThrow(() => TransactionCoinsValidator.Validate(new[] { coinToSpend }, coinsToReceive)); } }
private static IEnumerable <UMoney> Values() { yield return(UMoney.Create(10.0000m)); yield return(UMoney.Create(13.00m)); yield return(UMoney.Create(10.300000m)); }
public async Task Estimate_transfer_coins_transaction() { //ARRANGE var fees = new[] { new Fee(new Asset("asset"), UMoney.Create(1000, 4)) }; var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Estimate_transfer_coins_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransferCoinsTransactionsEstimator .Setup(x => x.EstimateTransferCoinsAsync(It.IsAny <EstimateTransferCoinsTransactionRequest>())) .ReturnsAsync(new EstimateTransactionResponse(fees)); }); //ACT var coinsToSpend = new[] { new CoinToSpend(new CoinId("tx1", 0), new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x1"), Base64String.Encode("context"), 1), }; var coinsToReceive = new[] { new CoinToReceive(0, new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x2"), new AddressTag("tag"), AddressTagType.Text ), }; var request = new EstimateTransferCoinsTransactionRequest(coinsToSpend, coinsToReceive); var result = await client.EstimateTransferCoinsTransactionAsync(request); //ASSERT Assert.NotNull(result); var estimation = result.EstimatedFees.SingleOrDefault(); Assert.NotNull(estimation); Assert.AreEqual(new Asset("asset"), estimation.Asset); Assert.AreEqual(UMoney.Create(1000, 4), estimation.Amount); }
public void Test_that_single_transfer_is_allowed() { TransactionTransfersValidator.Validate(new List <Transfer> { new Transfer ( new Asset("STEEM"), UMoney.Create(100, 3), "A", "B" ) }); }
public async Task Build_transfer_coins_transaction() { //ARRANGE string transactionResponse = "transactionResponse"; var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Build_transfer_coins_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransferCoinsTransactionsBuilder .Setup(x => x.BuildTransferCoinsAsync(It.IsAny <BuildTransferCoinsTransactionRequest>())) .ReturnsAsync(new BuildTransactionResponse(Base64String.Encode(transactionResponse))); }); //ACT var coinsToSpend = new[] { new CoinToSpend(new CoinId("tx1", 0), new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x1"), Base64String.Encode("context"), 1), }; var coinsToReceive = new[] { new CoinToReceive(0, new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x2"), new AddressTag("tag"), AddressTagType.Text ), }; var expirationOptions = new ExpirationOptions(DateTime.Now + TimeSpan.FromDays(1)); var request = new BuildTransferCoinsTransactionRequest(coinsToSpend, coinsToReceive, expirationOptions); var result = await client.BuildTransferCoinsTransactionAsync(request); //ASSERT Assert.True(result != null); Assert.True(result.TransactionContext.DecodeToString() == transactionResponse); }
public void Bad_request_transfer_coins_transaction() { //ARRANGE var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Bad_request_transfer_coins_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransferCoinsTransactionsBuilder .Setup(x => x.BuildTransferCoinsAsync(It.IsAny <BuildTransferCoinsTransactionRequest>())) .ThrowsAsync(new TransactionBuildingException(TransactionBuildingError.RetryLater, "some error")); }); //ACT && ASSERT var coinsToSpend = new[] { new CoinToSpend(new CoinId("tx1", 0), new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x1"), Base64String.Encode("context"), 1), }; var coinsToReceive = new[] { new CoinToReceive(0, new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x2"), new AddressTag("tag"), AddressTagType.Text ), }; var expirationOptions = new ExpirationOptions(DateTime.Now + TimeSpan.FromDays(1)); Assert.ThrowsAsync <TransactionBuildingWebApiException>(async() => { var request = new BuildTransferCoinsTransactionRequest(coinsToSpend, coinsToReceive, expirationOptions); await client.BuildTransferCoinsTransactionAsync(request); }); }
public void Internal_server_error_estimate_transfer_coins_transaction() { //ARRANGE var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Internal_server_error_estimate_transfer_coins_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransferCoinsTransactionsEstimator .Setup(x => x.EstimateTransferCoinsAsync(It.IsAny <EstimateTransferCoinsTransactionRequest>())) .ThrowsAsync(new Exception("some error")); }); //ACT && ASSERT var coinsToSpend = new[] { new CoinToSpend(new CoinId("tx1", 0), new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x1"), Base64String.Encode("context"), 1), }; var coinsToReceive = new[] { new CoinToReceive(0, new Asset("assetId"), UMoney.Create(1000, 4), new Address("0x2"), new AddressTag("tag"), AddressTagType.Text ), }; Assert.ThrowsAsync <InternalServerErrorWebApiException>(async() => { var request = new EstimateTransferCoinsTransactionRequest(coinsToSpend, coinsToReceive); await client.EstimateTransferCoinsTransactionAsync(request); }); }
public async Task ReadBlockAsync(long blockNumber, IBlockListener listener) { var blockId = Guid.NewGuid().ToString("N"); var previousBlockId = Guid.NewGuid().ToString("N"); listener.HandleRawBlock("raw-block".ToBase64(), blockId); var transactionsListener = listener.StartBlockTransactionsHandling ( new BlockHeaderReadEvent ( blockNumber, blockId, DateTime.UtcNow, 100, 1, previousBlockId ) ); var transactionId = new TransactionId(Guid.NewGuid().ToString("N")); await transactionsListener.HandleRawTransactionAsync("raw-transaction".ToBase64(), transactionId); transactionsListener.HandleExecutedTransaction ( new TransferAmountExecutedTransaction ( transactionNumber: 1, transactionId: transactionId, balanceChanges: new[] { new BalanceChange("1", new Asset("STEEM"), Money.Create(123, 4), "abc") }, fees: new[] { new Fee(new Asset("STEEM"), UMoney.Create(0.0001m, 4)), }, isIrreversible: true ) ); }
public void Nullable_Money_Should_Be_Serializable_To_Json() { // ReSharper disable once JoinDeclarationAndInitializer UMoney?value; value = UMoney.Create(10, 5); JsonConvert .SerializeObject(value) .Should() .Be("\"10.00000\""); value = null; JsonConvert // ReSharper disable once ExpressionIsAlwaysNull .SerializeObject(value) .Should() .Be("null"); }
public void Test_that_empty_collections_are_not_allowed() { // Arrange var coinToSpend = new CoinToSpend ( new CoinId("1", 1), new Asset("KIN"), UMoney.Create(100, 3), "A" ); var coinToReceive = new CoinToReceive ( 0, new Asset("KIN"), UMoney.Create(100, 3), "A" ); // Act, Throw Assert.Throws <RequestValidationException> ( () => TransactionCoinsValidator.Validate(null, new[] { coinToReceive }) ); Assert.Throws <RequestValidationException> ( () => TransactionCoinsValidator.Validate(Array.Empty <CoinToSpend>(), new[] { coinToReceive }) ); Assert.Throws <RequestValidationException> ( () => TransactionCoinsValidator.Validate(new[] { coinToSpend }, null) ); Assert.Throws <RequestValidationException> ( () => TransactionCoinsValidator.Validate(new[] { coinToSpend }, Array.Empty <CoinToReceive>()) ); }
public void Test_that_duplicated_transfers_are_not_allowed() { var transfers = new List <Transfer> { new Transfer ( new Asset("XRP"), UMoney.Create(100, 3), "A", "B" ), new Transfer ( new Asset("XRP"), UMoney.Create(80, 5), "A", "B" ) }; Assert.Throws <RequestValidationException>(() => TransactionTransfersValidator.Validate(transfers)); }
public async Task Estimate_transfer_amount_transaction() { //ARRANGE var fees = new[] { new Fee(new Asset("asset"), UMoney.Create(1000, 4)) }; var client = PrepareClient <AppSettings>((options) => { var aggregator = CreateMocksAndSetupFactories(options); options.IntegrationName = $"{nameof(TransactionExecutorClientTests)}+{nameof(Estimate_transfer_amount_transaction)}"; aggregator.HealthProvider.Setup(x => x.GetDiseaseAsync()).ReturnsAsync(Disease); aggregator.TransactionEstimator.Setup(x => x.EstimateTransferAmountAsync(It.IsAny <EstimateTransferAmountTransactionRequest>())) .ReturnsAsync(new EstimateTransactionResponse(fees)); }); //ACT var transfers = new[] { new Transfer( new Asset("asset"), UMoney.Create(1000000000, 4), new Address("x1"), new Address("x2")), }; var request = new EstimateTransferAmountTransactionRequest(transfers); var result = await client.EstimateTransferAmountTransactionAsync(request); //ASSERT Assert.NotNull(result); var estimation = result.EstimatedFees.SingleOrDefault(); Assert.NotNull(estimation); Assert.AreEqual(new Asset("asset"), estimation.Asset); Assert.AreEqual(UMoney.Create(1000, 4), estimation.Amount); }
public void Test_that_sum_of_coins_to_send_equal_or_greater_than_sum_to_receive_for_each_assets(string assetsToSpend, string assetsToReceive, bool shouldThrow) { // Arrange var coinsToSpend = assetsToSpend .Split(',') .Select(x => x.Split(':')) .Select(x => new CoinToSpend ( new CoinId("1", 1), new Asset(x[0]), UMoney.Create(int.Parse(x[1]), 3), "A" )) .ToArray(); var coinsToReceive = assetsToReceive .Split(',') .Select(x => x.Split(':')) .Select((x, i) => new CoinToReceive ( i, new Asset(x[0]), UMoney.Create(int.Parse(x[1]), 3), "A" )) .ToArray(); // Act, Throw if (shouldThrow) { Assert.Throws <RequestValidationException>(() => TransactionCoinsValidator.Validate(coinsToSpend, coinsToReceive)); } else { Assert.DoesNotThrow(() => TransactionCoinsValidator.Validate(coinsToSpend, coinsToReceive)); } }
public void Test_that_sets_of_assets_should_match(string assetsToSpend, string assetsToReceive, bool shouldThrow) { // Arrange var coinsToSpend = assetsToSpend .Split(',') .Select(asset => new CoinToSpend ( new CoinId("1", 1), new Asset(asset), UMoney.Create(100, 3), "A" )) .ToArray(); var coinsToReceive = assetsToReceive .Split(',') .Select((asset, i) => new CoinToReceive ( i, new Asset(asset), UMoney.Create(100, 3), "A" )) .ToArray(); // Act, Throw if (shouldThrow) { Assert.Throws <RequestValidationException>(() => TransactionCoinsValidator.Validate(coinsToSpend, coinsToReceive)); } else { Assert.DoesNotThrow(() => TransactionCoinsValidator.Validate(coinsToSpend, coinsToReceive)); } }
public void Test_that_multiple_transfers_are_allowed( string asset1, string asset2, string asset3, string source1, string source2, string source3, string destination1, string destination2, string destination3) { TransactionTransfersValidator.Validate(new List <Transfer> { new Transfer ( new Asset(asset1), UMoney.Create(100, 3), source1, destination1 ), new Transfer ( new Asset(asset2), UMoney.Create(80, 5), source2, destination2 ), new Transfer ( new Asset(asset3), UMoney.Create(80, 5), source3, destination3 ) }); }
public async Task Block_listener_test() { //ARRANGE Mock <IRawObjectWriteOnlyRepository> rawObjectsRepository = null; var typeWaitHandles = new Dictionary <Type, ManualResetEventSlim>() { { typeof(BlockHeaderReadEvent), new ManualResetEventSlim() }, { typeof(BlockNotFoundEvent), new ManualResetEventSlim() }, { typeof(TransferAmountTransactionsBatchEvent), new ManualResetEventSlim() }, }; var blockEventsHandlerMock = BlockEventsHandlerCreateMock((intName, evt, headers, messagePublisher) => { if (typeWaitHandles.TryGetValue(evt.GetType(), out var eventWaitHandle)) { eventWaitHandle.Set(); } }); var(client, apiFactory, testServer) = PrepareClient <AppSettings>( serverOptions => { CreateMocks( out var blockReader, out var blockProvider); rawObjectsRepository = new Mock <IRawObjectWriteOnlyRepository>(); rawObjectsRepository .Setup(x => x.SaveAsync(RawObjectType.Transaction, It.IsNotNull <string>(), It.IsNotNull <Base64String>())) .Returns(Task.CompletedTask) .Verifiable(); async void CallBack(long blockNumber, IBlockListener blockListener) { if (blockNumber == 2) { blockListener.HandleNotFoundBlock(new BlockNotFoundEvent(blockNumber)); return; } var asset = new Asset("assetId"); blockListener.HandleRawBlock(Base64String.Encode("raw-block"), "1"); var transactionsListener = blockListener.StartBlockTransactionsHandling ( new BlockHeaderReadEvent ( 1, "1", DateTime.UtcNow, 256, 5 ) ); await transactionsListener.HandleRawTransactionAsync(Base64String.Encode("transaction.raw"), "tr1"); transactionsListener.HandleExecutedTransaction ( new TransferAmountExecutedTransaction ( 1, "tr1", new[] { new BalanceChange ( "1", asset, Money.Create(1000, 4), new Address("0x2"), new AddressTag("tag"), AddressTagType.Text, 1) }, new[] { new Fee(asset, UMoney.Create(10, 4)) }, true ) ); await transactionsListener.HandleRawTransactionAsync(Base64String.Encode("transaction.raw"), "tr2"); transactionsListener.HandleExecutedTransaction ( new TransferAmountExecutedTransaction ( 2, "tr2", new[] { new BalanceChange ( "1", asset, Money.Create(100, 4), new Address("0x3"), new AddressTag("tag"), AddressTagType.Text, 2) }, new[] { new Fee(asset, UMoney.Create(10, 4)) }, true ) ); await transactionsListener.HandleRawTransactionAsync(Base64String.Encode("transaction.raw"), "tr3"); transactionsListener.HandleExecutedTransaction ( new TransferAmountExecutedTransaction ( 3, "tr3", new[] { new BalanceChange ( "1", asset, Money.Create(500, 4), new Address("0x4"), new AddressTag("tag"), AddressTagType.Text, 3) }, new[] { new Fee(asset, UMoney.Create(10, 4)) }, true ) ); await transactionsListener.HandleRawTransactionAsync(Base64String.Encode("transaction.raw"), "tr4"); transactionsListener.HandleFailedTransaction ( new FailedTransaction ( 4, "tr4", TransactionBroadcastingError.TransientFailure, "some error message", new[] { new Fee(asset, UMoney.Create(10, 4)) } ) ); await transactionsListener.HandleRawTransactionAsync(Base64String.Encode("transaction.raw"), "tr5"); transactionsListener.HandleFailedTransaction ( new FailedTransaction ( 5, "tr5", TransactionBroadcastingError.TransientFailure, "some error message", new[] { new Fee(asset, UMoney.Create(10, 4)) } ) ); } serverOptions.IntegrationName = _integrationName; serverOptions.UseTransferAmountTransactionsModel(); blockReader .Setup(x => x.ReadBlockAsync(It.IsAny <long>(), It.IsAny <IBlockListener>())) .Returns(Task.CompletedTask) .Callback((Action <long, IBlockListener>)CallBack); serverOptions.UseSettings = (services, set) => { services.AddSingleton(rawObjectsRepository.Object); }; ConfigureFactories(serverOptions, blockReader, blockProvider, false);//pushing is set here }, clientOptions => { clientOptions.BlockEventsHandlerFactory = context => blockEventsHandlerMock.Object; clientOptions.RabbitVhost = _rabbitMqSettings.Vhost; clientOptions.RabbitMqConnString = _rabbitMqSettings.GetConnectionString(); clientOptions.AddIntegration(_integrationName); }); var block1CorrelationId = "correlation-id-1"; var block2CorrelationId = "correlation-id-2"; //ACT using (testServer) using (client) { client.Initialize(); client.StartListening(); var apiBlocksReader = apiFactory.Create(_integrationName); await apiBlocksReader.SendAsync(new ReadBlockCommand(1), block1CorrelationId); await apiBlocksReader.SendAsync(new ReadBlockCommand(2), block2CorrelationId); foreach (var manualResetEventSlim in typeWaitHandles) { if (!manualResetEventSlim.Value.Wait(Waiting.Timeout)) { Console.WriteLine($"Event {manualResetEventSlim.Key} has been missed!"); } } } //ASSERT rawObjectsRepository .Verify(x => x.SaveAsync(RawObjectType.Transaction, It.IsNotNull <string>(), It.IsNotNull <Base64String>()), Times.AtLeast(3)); rawObjectsRepository .Verify(x => x.SaveAsync(RawObjectType.Block, It.IsNotNull <string>(), It.IsNotNull <Base64String>()), Times.AtLeast(1)); blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <BlockHeaderReadEvent>(b => b.BlockId == "1"), It.Is <MessageHeaders>(h => h.CorrelationId == block1CorrelationId), It.IsNotNull <IMessagePublisher>()), Times.AtLeastOnce); blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <BlockHeaderReadEvent>(b => b.BlockId != "1"), It.IsNotNull <MessageHeaders>(), It.IsNotNull <IMessagePublisher>()), Times.Never); blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <BlockNotFoundEvent>(b => b.BlockNumber == 2), It.Is <MessageHeaders>(h => h.CorrelationId == block2CorrelationId), It.IsNotNull <IMessagePublisher>()), Times.AtLeastOnce); blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <BlockNotFoundEvent>(b => b.BlockNumber != 2), It.IsNotNull <MessageHeaders>(), It.IsNotNull <IMessagePublisher>()), Times.Never); // Batch 1 blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <TransferAmountTransactionsBatchEvent>(b => b.BlockId == "1" && b.FailedTransactions.Count == 0 && b.TransferAmountExecutedTransactions.Count == 2), It.Is <MessageHeaders>(h => h.CorrelationId == block1CorrelationId), It.IsNotNull <IMessagePublisher>()), Times.AtLeastOnce); // Batch 2 blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <TransferAmountTransactionsBatchEvent>(b => b.BlockId == "1" && b.FailedTransactions.Count == 1 && b.TransferAmountExecutedTransactions.Count == 1), It.Is <MessageHeaders>(h => h.CorrelationId == block1CorrelationId), It.IsNotNull <IMessagePublisher>()), Times.AtLeastOnce); // Batch 3 blockEventsHandlerMock .Verify(x => x.HandleAsync( _integrationName, It.Is <TransferAmountTransactionsBatchEvent>(b => b.BlockId == "1" && b.FailedTransactions.Count == 1 && b.TransferAmountExecutedTransactions.Count == 0), It.Is <MessageHeaders>(h => h.CorrelationId == block1CorrelationId), It.IsNotNull <IMessagePublisher>()), Times.AtLeastOnce); }