From eacc11515b34f7b14449365f7b8317a0b362ae65 Mon Sep 17 00:00:00 2001
From: Malhar Khimsaria <96malhar@gmail.com>
Date: Tue, 6 Aug 2024 10:44:15 -0700
Subject: [PATCH] Add the ability to mock BatchWrite and MultiTableBatchWrite
operations
---
sdk/src/Core/AWSSDK.Core.NetFramework.csproj | 2 +-
sdk/src/Core/AWSSDK.Core.NetStandard.csproj | 2 +-
.../DynamoDBv2/Custom/DataModel/BatchWrite.cs | 270 ++++++++----------
.../DynamoDBv2/Custom/DataModel/Context.cs | 85 +-----
.../Custom/DataModel/IDynamoDBContext.cs | 14 +-
.../DataModel/_async/BatchWrite.Async.cs | 47 ++-
.../Custom/DataModel/_async/Context.Async.cs | 12 +-
.../_async/IDynamoDBContext.Async.cs | 2 +-
.../Custom/DataModel/_bcl/BatchWrite.Sync.cs | 47 ++-
.../Custom/DataModel/_bcl/Context.Sync.cs | 9 +-
.../DataModel/_bcl/IDynamoDBContext.Sync.cs | 3 +-
.../Custom/MockabilityTests/BatchGetTests.cs | 2 +-
.../MockabilityTests/BatchWriteTests.cs | 121 ++++++++
13 files changed, 315 insertions(+), 301 deletions(-)
create mode 100644 sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs
diff --git a/sdk/src/Core/AWSSDK.Core.NetFramework.csproj b/sdk/src/Core/AWSSDK.Core.NetFramework.csproj
index 3d740253846d..aa96aa545da5 100644
--- a/sdk/src/Core/AWSSDK.Core.NetFramework.csproj
+++ b/sdk/src/Core/AWSSDK.Core.NetFramework.csproj
@@ -69,6 +69,6 @@
-
+
diff --git a/sdk/src/Core/AWSSDK.Core.NetStandard.csproj b/sdk/src/Core/AWSSDK.Core.NetStandard.csproj
index 2af0a0429fbb..5bbd2016d82d 100644
--- a/sdk/src/Core/AWSSDK.Core.NetStandard.csproj
+++ b/sdk/src/Core/AWSSDK.Core.NetStandard.csproj
@@ -81,6 +81,6 @@
-
+
\ No newline at end of file
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs
index 99958b020eb2..8c45afba89ea 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/BatchWrite.cs
@@ -14,10 +14,7 @@
*/
using System;
-using System.Collections;
using System.Collections.Generic;
-using System.Reflection;
-using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DocumentModel;
using System.Globalization;
#if AWS_ASYNC_API
@@ -28,56 +25,19 @@
namespace Amazon.DynamoDBv2.DataModel
{
///
- /// Represents a non-generic object for writing/deleting a batch of items
+ /// Represents a non-generic interface for writing/deleting a batch of items
/// in a single DynamoDB table
///
- public abstract partial class BatchWrite
+ public partial interface IBatchWrite
{
- #region Internal/protected properties
-
- internal DynamoDBContext Context { get; set; }
- internal DynamoDBFlatConfig Config { get; set; }
- internal DocumentBatchWrite DocumentBatch { get; set; }
-
- #endregion
-
-
- #region Constructor
-
- internal BatchWrite(DynamoDBContext context, DynamoDBFlatConfig config)
- {
- Context = context;
- Config = config;
- }
-
- #endregion
-
-
- #region Protected methods
-
- ///
- /// Executes a server call to batch-write/delete the items requested.
- ///
- internal protected abstract void ExecuteHelper();
-
-#if AWS_ASYNC_API
- ///
- /// Executes an asynchronous server call to batch-write/delete the items requested.
- ///
- internal protected abstract Task ExecuteHelperAsync(CancellationToken cancellationToken);
-#endif
-
- #endregion
}
///
- /// Represents a strongly-typed object for writing/deleting a batch of items
+ /// Represents a generic interface for writing/deleting a batch of items
/// in a single DynamoDB table
///
- public class BatchWrite : BatchWrite
+ public interface IBatchWrite : IBatchWrite
{
- #region Public combine methods
-
///
/// Creates a MultiTableBatchWrite object that is a combination
/// of the current BatchWrite and the specified BatchWrites
@@ -87,84 +47,38 @@ public class BatchWrite : BatchWrite
/// MultiTableBatchWrite consisting of the multiple BatchWrite objects:
/// the current batch and the passed-in batches.
///
- public MultiTableBatchWrite Combine(params BatchWrite[] otherBatches)
- {
- return new MultiTableBatchWrite(this, otherBatches);
- }
-
- #endregion
-
-
- #region Public Put methods
+ IMultiTableBatchWrite Combine(params IBatchWrite[] otherBatches);
///
/// Add a number of items to be put in the current batch operation
///
/// Items to put
- public void AddPutItems(IEnumerable values)
- {
- if (values == null) return;
-
- foreach (T item in values)
- {
- AddPutItem(item);
- }
- }
+ void AddPutItems(IEnumerable values);
///
/// Add a single item to be put in the current batch operation
///
///
- public void AddPutItem(T item)
- {
- if (item == null) return;
-
- ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: false, ignoreNullValues: true);
- if (storage == null) return;
- DocumentBatch.AddDocumentToPut(storage.Document);
- }
-
- #endregion
-
-
- #region Public Delete methods
+ void AddPutItem(T item);
///
/// Add a number of items to be deleted in the current batch operation
///
/// Items to be deleted
- public void AddDeleteItems(IEnumerable values)
- {
- if (values == null) return;
-
- foreach (T item in values)
- {
- AddDeleteItem(item);
- }
- }
+ void AddDeleteItems(IEnumerable values);
///
/// Add a single item to be deleted in the current batch operation.
///
/// Item to be deleted
- public void AddDeleteItem(T item)
- {
- if (item == null) return;
-
- ItemStorage storage = Context.ObjectToItemStorageHelper(item, StorageConfig, Config, keysOnly: true, ignoreNullValues: true);
- if (storage == null) return;
- DocumentBatch.AddItemToDelete(storage.Document);
- }
+ void AddDeleteItem(T item);
///
/// Add a single item to be deleted in the current batch operation.
/// Item is identified by its hash primary key.
///
/// Hash key of the item to delete
- public void AddDeleteKey(object hashKey)
- {
- AddDeleteKey(hashKey, null);
- }
+ void AddDeleteKey(object hashKey);
///
/// Add a single item to be deleted in the current batch operation.
@@ -172,15 +86,27 @@ public void AddDeleteKey(object hashKey)
///
/// Hash key of the item to delete
/// Range key of the item to delete
- public void AddDeleteKey(object hashKey, object rangeKey)
- {
- DocumentBatch.AddKeyToDelete(Context.MakeKey(hashKey, rangeKey, StorageConfig, Config));
- }
-
- #endregion
+ void AddDeleteKey(object hashKey, object rangeKey);
+ }
+ ///
+ /// Represents a non-generic object for writing/deleting a batch of items
+ /// in a single DynamoDB table
+ ///
+ public abstract partial class BatchWrite : IBatchWrite
+ {
+ internal DocumentBatchWrite DocumentBatch { get; set; }
+ }
- #region Constructor
+ ///
+ /// Represents a strongly-typed object for writing/deleting a batch of items
+ /// in a single DynamoDB table
+ ///
+ public partial class BatchWrite : BatchWrite, IBatchWrite
+ {
+ private readonly DynamoDBContext _context;
+ private readonly DynamoDBFlatConfig _config;
+ private readonly ItemStorageConfig _storageConfig;
internal BatchWrite(DynamoDBContext context, DynamoDBFlatConfig config)
: this(context, typeof(T), config)
@@ -188,118 +114,164 @@ internal BatchWrite(DynamoDBContext context, DynamoDBFlatConfig config)
}
internal BatchWrite(DynamoDBContext context, Type valuesType, DynamoDBFlatConfig config)
- : base(context, config)
{
- StorageConfig = context.StorageConfigCache.GetConfig(valuesType, config);
+ _context = context;
+ _config = config;
+ _storageConfig = context.StorageConfigCache.GetConfig(valuesType, config);
- if (StorageConfig.HasVersion)
+ if (_storageConfig.HasVersion)
{
- if (!Config.SkipVersionCheck.GetValueOrDefault(false))
+ if (!_config.SkipVersionCheck.GetValueOrDefault(false))
throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture,
"Object {0} has a versioning field, which is not supported for this operation. To ignore versioning, use the DynamoDBContextConfig.SkipVersionCheck property.",
valuesType.Name));
}
- Table table = Context.GetTargetTable(StorageConfig, Config);
+ Table table = _context.GetTargetTable(_storageConfig, _config);
DocumentBatch = table.CreateBatchWrite();
}
- #endregion
+ ///
+ public IMultiTableBatchWrite Combine(params IBatchWrite[] otherBatches)
+ {
+ return new MultiTableBatchWrite(this, otherBatches);
+ }
+ ///
+ public void AddPutItems(IEnumerable values)
+ {
+ if (values == null) return;
- #region Internal/protected/private members
+ foreach (T item in values)
+ {
+ AddPutItem(item);
+ }
+ }
- internal ItemStorageConfig StorageConfig { get; set; }
+ ///
+ public void AddPutItem(T item)
+ {
+ if (item == null) return;
- ///
- /// Execute the batch write.
- ///
- internal protected override void ExecuteHelper()
+ ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: false, ignoreNullValues: true);
+ if (storage == null) return;
+ DocumentBatch.AddDocumentToPut(storage.Document);
+ }
+
+ ///
+ public void AddDeleteItems(IEnumerable values)
+ {
+ if (values == null) return;
+
+ foreach (T item in values)
+ {
+ AddDeleteItem(item);
+ }
+ }
+
+ ///
+ public void AddDeleteItem(T item)
+ {
+ if (item == null) return;
+
+ ItemStorage storage = _context.ObjectToItemStorageHelper(item, _storageConfig, _config, keysOnly: true, ignoreNullValues: true);
+ if (storage == null) return;
+ DocumentBatch.AddItemToDelete(storage.Document);
+ }
+
+ ///
+ public void AddDeleteKey(object hashKey)
+ {
+ AddDeleteKey(hashKey, null);
+ }
+
+ ///
+ public void AddDeleteKey(object hashKey, object rangeKey)
+ {
+ DocumentBatch.AddKeyToDelete(_context.MakeKey(hashKey, rangeKey, _storageConfig, _config));
+ }
+
+ private void ExecuteHelper()
{
DocumentBatch.ExecuteHelper();
}
#if AWS_ASYNC_API
- ///
- /// Execute the batch write asynchronously.
- ///
- internal protected override Task ExecuteHelperAsync(CancellationToken cancellationToken)
+ private Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
return DocumentBatch.ExecuteHelperAsync(cancellationToken);
}
#endif
+ }
- #endregion
+ ///
+ /// Interface for writing/deleting a batch of items in multiple DynamoDB tables,
+ /// using multiple strongly-typed BatchWrite objects
+ ///
+ public partial interface IMultiTableBatchWrite
+ {
+ ///
+ /// Add a BatchWrite object to the multi-table batch request
+ ///
+ /// BatchWrite to add
+ void AddBatch(IBatchWrite batch);
}
///
/// Class for writing/deleting a batch of items in multiple DynamoDB tables,
/// using multiple strongly-typed BatchWrite objects
///
- public partial class MultiTableBatchWrite
+ public partial class MultiTableBatchWrite : IMultiTableBatchWrite
{
- #region Private members
-
- private List allBatches = new List();
-
- #endregion
-
-
- #region Constructor
+ private List allBatches = new();
///
/// Constructs a MultiTableBatchWrite object from a number of
/// BatchWrite objects
///
/// Collection of BatchWrite objects
- public MultiTableBatchWrite(params BatchWrite[] batches)
+ public MultiTableBatchWrite(params IBatchWrite[] batches)
{
- allBatches = new List(batches);
+ allBatches = new List(batches);
}
- internal MultiTableBatchWrite(BatchWrite first, params BatchWrite[] rest)
+ internal MultiTableBatchWrite(IBatchWrite first, params IBatchWrite[] rest)
{
- allBatches = new List();
+ allBatches = new List();
allBatches.Add(first);
allBatches.AddRange(rest);
}
- #endregion
-
-
- #region Public methods
-
- ///
- /// Add a BatchWrite object to the multi-table batch request
- ///
- /// BatchGet to add
- public void AddBatch(BatchWrite batch)
+ ///
+ public void AddBatch(IBatchWrite batch)
{
allBatches.Add(batch);
}
- internal void ExecuteHelper()
+ private void ExecuteHelper()
{
MultiTableDocumentBatchWrite superBatch = new MultiTableDocumentBatchWrite();
+ var errorMsg = $"All batches must be of type {nameof(BatchWrite)}";
foreach (var batch in allBatches)
{
- superBatch.AddBatch(batch.DocumentBatch);
+ var abstractBatch = batch as BatchWrite ?? throw new InvalidOperationException(errorMsg);
+ superBatch.AddBatch(abstractBatch.DocumentBatch);
}
superBatch.ExecuteHelper();
}
#if AWS_ASYNC_API
- internal Task ExecuteHelperAsync(CancellationToken cancellationToken)
+ private Task ExecuteHelperAsync(CancellationToken cancellationToken)
{
MultiTableDocumentBatchWrite superBatch = new MultiTableDocumentBatchWrite();
+ var errorMsg = $"All batches must be of type {nameof(BatchWrite)}";
foreach (var batch in allBatches)
{
- superBatch.AddBatch(batch.DocumentBatch);
+ var abstractBatch = batch as BatchWrite ?? throw new InvalidOperationException(errorMsg);
+ superBatch.AddBatch(abstractBatch.DocumentBatch);
}
return superBatch.ExecuteHelperAsync(cancellationToken);
}
#endif
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs
index b16b61b105d3..3012c9089c93 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/Context.cs
@@ -239,105 +239,48 @@ public IMultiTableBatchGet CreateMultiTableBatchGet(params IBatchGet[] batches)
#region BatchWrite
- ///
- /// Creates a strongly-typed BatchWrite object, allowing
- /// a batch-write operation against DynamoDB.
- ///
- /// Type of objects to write
- /// Empty strongly-typed BatchWrite object
- public BatchWrite CreateBatchWrite()
+ ///
+ public IBatchWrite CreateBatchWrite()
{
return CreateBatchWrite((BatchWriteConfig)null);
}
- ///
- /// Creates a strongly-typed BatchWrite object, allowing
- /// a batch-write operation against DynamoDB.
- ///
- /// Type of objects to write
- /// Config object which can be used to override that table used.
- /// Empty strongly-typed BatchWrite object
+ ///
[Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")]
- public BatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig)
+ public IBatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig)
{
DynamoDBFlatConfig config = new DynamoDBFlatConfig(operationConfig, this.Config);
return new BatchWrite(this, config);
}
- ///
- /// Creates a strongly-typed BatchWrite object, allowing
- /// a batch-write operation against DynamoDB.
- ///
- /// This is intended for use only when the valuesType is not known at compile-time, for example,
- /// when hooking into EF's ChangeTracker to record audit logs from EF into DynamoDB.
- ///
- /// In scenarios when the valuesType is known at compile-time, the
- /// method is generally preferred.
- ///
- /// Type of objects to write
- /// Empty strongly-typed BatchWrite object
- public BatchWrite
/// Type of objects to write
/// Empty strongly-typed BatchWrite object
- BatchWrite CreateBatchWrite();
+ IBatchWrite CreateBatchWrite();
///
/// Creates a strongly-typed BatchWrite object, allowing
@@ -203,7 +203,7 @@ public partial interface IDynamoDBContext : IDisposable
/// Empty strongly-typed BatchWrite object
[Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")]
- BatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig = null);
+ IBatchWrite CreateBatchWrite(DynamoDBOperationConfig operationConfig = null);
///
/// Creates a strongly-typed BatchWrite object, allowing
@@ -217,7 +217,7 @@ public partial interface IDynamoDBContext : IDisposable
///
/// The type of data which will be persisted in this batch.
/// Empty strongly-typed BatchWrite object
- BatchWrite CreateBatchWrite(Type valuesType);
+ IBatchWrite CreateBatchWrite(Type valuesType);
///
/// Creates a strongly-typed BatchWrite object, allowing
@@ -233,7 +233,7 @@ public partial interface IDynamoDBContext : IDisposable
/// Config object which can be used to override that table used.
/// Empty strongly-typed BatchWrite object
[Obsolete("Use the CreateBatchWrite overload that takes BatchWriteConfig instead, since DynamoDBOperationConfig contains properties that are not applicable to BatchWrite.")]
- BatchWrite CreateBatchWrite(Type valuesType, DynamoDBOperationConfig operationConfig = null);
+ IBatchWrite CreateBatchWrite(Type valuesType, DynamoDBOperationConfig operationConfig = null);
///
/// Creates a strongly-typed BatchWrite object, allowing
@@ -242,7 +242,7 @@ public partial interface IDynamoDBContext : IDisposable
/// Type of objects to write
/// Config object that can be used to override properties on the table's context for this request.
/// Empty strongly-typed BatchWrite object
- BatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig);
+ IBatchWrite CreateBatchWrite(BatchWriteConfig batchWriteConfig);
///
/// Creates a strongly-typed BatchWrite object, allowing
@@ -257,7 +257,7 @@ public partial interface IDynamoDBContext : IDisposable
/// The type of data which will be persisted in this batch.
/// Config object that can be used to override properties on the table's context for this request.
/// Empty strongly-typed BatchWrite object
- BatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig);
+ IBatchWrite CreateBatchWrite(Type valuesType, BatchWriteConfig batchWriteConfig);
///
/// Creates a MultiTableBatchWrite object, composed of multiple
@@ -265,7 +265,7 @@ public partial interface IDynamoDBContext : IDisposable
///
/// Individual BatchWrite objects
/// Composite MultiTableBatchWrite object
- MultiTableBatchWrite CreateMultiTableBatchWrite(params BatchWrite[] batches);
+ IMultiTableBatchWrite CreateMultiTableBatchWrite(params IBatchWrite[] batches);
#endregion
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs
index 4f4cdc0d4789..ec77b8766dd5 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/BatchWrite.Async.cs
@@ -14,26 +14,13 @@
*/
#pragma warning disable 1574
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using Amazon.DynamoDBv2.Model;
-using Amazon.DynamoDBv2.DocumentModel;
using System.Threading.Tasks;
-using Amazon.Runtime.Internal;
using System.Threading;
namespace Amazon.DynamoDBv2.DataModel
{
- ///
- /// Represents a non-generic object for writing/deleting a batch of items
- /// in a single DynamoDB table
- ///
- public abstract partial class BatchWrite
+ public partial interface IBatchWrite
{
- #region Public methods
-
///
/// Executes a server call to batch-write/delete the items requested.
///
@@ -43,22 +30,26 @@ public abstract partial class BatchWrite
/// Token which can be used to cancel the task.
///
/// A Task that can be used to poll or wait for results, or both.
- public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public abstract partial class BatchWrite : IBatchWrite
+ {
+ ///
+ public abstract Task ExecuteAsync(CancellationToken cancellationToken);
+ }
+
+ public partial class BatchWrite : BatchWrite, IBatchWrite
+ {
+ ///
+ public override Task ExecuteAsync(CancellationToken cancellationToken)
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
- ///
- /// Class for writing/deleting a batch of items in multiple DynamoDB tables,
- /// using multiple strongly-typed BatchWrite objects
- ///
- public partial class MultiTableBatchWrite
+ public partial interface IMultiTableBatchWrite
{
- #region Public methods
-
///
/// Executes a multi-table batch request against all configured batches.
///
@@ -68,11 +59,15 @@ public partial class MultiTableBatchWrite
/// Token which can be used to cancel the task.
///
/// A Task that can be used to poll or wait for results, or both.
+ Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken));
+ }
+
+ public partial class MultiTableBatchWrite : IMultiTableBatchWrite
+ {
+ ///
public Task ExecuteAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return ExecuteHelperAsync(cancellationToken);
}
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs
index 8ca209c1a640..a408abb50e5a 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/Context.Async.cs
@@ -211,16 +211,8 @@ public Task ExecuteBatchGetAsync(params IBatchGet[] batches)
#region BatchWrite async
- ///
- /// Issues a batch-write request with multiple batches.
- ///
- ///
- /// Configured BatchWrite objects
- ///
- ///
- /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
- ///
- public Task ExecuteBatchWriteAsync(BatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken))
+ ///
+ public Task ExecuteBatchWriteAsync(IBatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken))
{
MultiTableBatchWrite superBatch = new MultiTableBatchWrite(batches);
return superBatch.ExecuteAsync(cancellationToken);
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs
index 5b49fdbd525f..35faea1bba77 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_async/IDynamoDBContext.Async.cs
@@ -422,7 +422,7 @@ partial interface IDynamoDBContext
///
/// Token which can be used to cancel the task.
/// A Task that can be used to poll or wait for results, or both.
- Task ExecuteBatchWriteAsync(BatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken));
+ Task ExecuteBatchWriteAsync(IBatchWrite[] batches, CancellationToken cancellationToken = default(CancellationToken));
#endregion
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs
index e1da85c60993..68da3b2737fd 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/BatchWrite.Sync.cs
@@ -13,56 +13,51 @@
* permissions and limitations under the License.
*/
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using Amazon.DynamoDBv2.Model;
-using Amazon.DynamoDBv2.DocumentModel;
-
namespace Amazon.DynamoDBv2.DataModel
{
- ///
- /// Represents a non-generic object for writing/deleting a batch of items
- /// in a single DynamoDB table
- ///
- public abstract partial class BatchWrite
+ public partial interface IBatchWrite
{
- #region Public methods
-
///
/// Executes a server call to batch-write/delete the items requested.
///
/// If more than 25 put/delete operations are specified, calls of up to 25
/// put/delete items will be made until all items are processed.
///
- public void Execute()
+ void Execute();
+ }
+
+ public abstract partial class BatchWrite : IBatchWrite
+ {
+ ///
+ public abstract void Execute();
+ }
+
+ public partial class BatchWrite : BatchWrite, IBatchWrite
+ {
+ ///
+ public override void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
- ///
- /// Class for writing/deleting a batch of items in multiple DynamoDB tables,
- /// using multiple strongly-typed BatchWrite objects
- ///
- public partial class MultiTableBatchWrite
+ public partial interface IMultiTableBatchWrite
{
- #region Public methods
-
///
/// Executes a multi-table batch request against all configured batches.
///
/// If more than 25 put/delete operations are specified, calls of up to 25
/// put/delete items will be made until all items are processed.
///
+ void Execute();
+ }
+
+ public partial class MultiTableBatchWrite : IMultiTableBatchWrite
+ {
+ ///
public void Execute()
{
ExecuteHelper();
}
-
- #endregion
}
}
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs
index a53c03bbb1fa..ea57d246b026 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/Context.Sync.cs
@@ -195,13 +195,8 @@ public void ExecuteTransactGet(params TransactGet[] transactionParts)
#region Batch Write
- ///
- /// Issues a batch-write request with multiple batches.
- ///
- ///
- /// Configured BatchWrite objects
- ///
- public void ExecuteBatchWrite(params BatchWrite[] batches)
+ ///
+ public void ExecuteBatchWrite(params IBatchWrite[] batches)
{
MultiTableBatchWrite superBatch = new MultiTableBatchWrite(batches);
superBatch.Execute();
diff --git a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs
index 3ddc517527b8..eb6e2c58cb9b 100644
--- a/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs
+++ b/sdk/src/Services/DynamoDBv2/Custom/DataModel/_bcl/IDynamoDBContext.Sync.cs
@@ -13,6 +13,7 @@
* permissions and limitations under the License.
*/
+using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2.DocumentModel;
@@ -351,7 +352,7 @@ partial interface IDynamoDBContext
///
/// Configured BatchWrite objects
///
- void ExecuteBatchWrite(params BatchWrite[] batches);
+ void ExecuteBatchWrite(params IBatchWrite[] batches);
#endregion
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs
index 7d7ce4df13f1..a739c29a53fc 100644
--- a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchGetTests.cs
@@ -13,7 +13,7 @@ public void TestMockability_BatchGet()
{
var mockContext = new Mock();
mockContext
- .Setup(x => x.CreateBatchGet(It.IsAny()))
+ .Setup(x => x.CreateBatchGet())
.Returns(CreateBatchGetMock(new List()
{
{ new Address() { State = "CA", Zip = "12345" }}
diff --git a/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs
new file mode 100644
index 000000000000..86cd83e428be
--- /dev/null
+++ b/sdk/test/Services/DynamoDBv2/UnitTests/Custom/MockabilityTests/BatchWriteTests.cs
@@ -0,0 +1,121 @@
+using Amazon.DynamoDBv2.DataModel;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using System.Collections.Generic;
+
+namespace AWSSDK.UnitTests.DynamoDBv2.NetFramework.Custom.MockabilityTests
+{
+ [TestClass]
+ public class BatchWriteTests
+ {
+ [TestMethod]
+ public void TestMockability_BatchWrite()
+ {
+ var itemsToPut = new List();
+ var inMemoryTable = new List();
+
+ var mockContext = new Mock();
+ mockContext
+ .Setup(x => x.CreateBatchWrite())
+ .Returns(CreateBatchWriteMock(itemsToPut, inMemoryTable));
+
+ var ddbContext = mockContext.Object;
+ var batchWrite = ddbContext.CreateBatchWrite();
+
+ Assert.AreEqual(0, inMemoryTable.Count);
+ Assert.AreEqual(0, itemsToPut.Count);
+
+ batchWrite.AddPutItem("item1");
+ batchWrite.AddPutItem("item2");
+ Assert.AreEqual(2, itemsToPut.Count);
+ Assert.AreEqual(0, inMemoryTable.Count);
+
+ batchWrite.Execute();
+ Assert.AreEqual(0, itemsToPut.Count);
+ Assert.AreEqual(2, inMemoryTable.Count);
+ Assert.IsTrue(inMemoryTable.Contains("item1"));
+ Assert.IsTrue(inMemoryTable.Contains("item2"));
+ }
+
+ [TestMethod]
+ public void TestMockability_MultiTableBatchWrite()
+ {
+ var itemsToPut_table1 = new List();
+ var inMemory_table1 = new List();
+ var batchWrite_table1 = CreateBatchWriteMock(itemsToPut_table1, inMemory_table1);
+ batchWrite_table1.AddPutItem("item1");
+
+ var itemsToPut_table2 = new List();
+ var inMemory_table2 = new List();
+ var batchWrite_table2 = CreateBatchWriteMock(itemsToPut_table2, inMemory_table2);
+ batchWrite_table2.AddPutItem("item2");
+
+ var mockContext = new Mock();
+ mockContext
+ .Setup(x => x.CreateMultiTableBatchWrite())
+ .Returns(CreateMultiTableBatchWriteMock());
+
+ var ddbContext = mockContext.Object;
+ var multiBatchWrite = ddbContext.CreateMultiTableBatchWrite();
+ multiBatchWrite.AddBatch(batchWrite_table1);
+ multiBatchWrite.AddBatch(batchWrite_table2);
+
+ Assert.AreEqual(0, inMemory_table1.Count);
+ Assert.AreEqual(0, inMemory_table2.Count);
+
+ multiBatchWrite.Execute();
+ Assert.AreEqual(1, inMemory_table1.Count);
+ Assert.AreEqual(1, inMemory_table2.Count);
+ Assert.IsTrue(inMemory_table1.Contains("item1"));
+ Assert.IsTrue(inMemory_table2.Contains("item2"));
+ }
+
+ public IBatchWrite CreateBatchWriteMock(List itemsToPut, List inMemoryTable)
+ {
+ var batchWrite = new Mock>();
+
+ batchWrite
+ .Setup(x => x.AddPutItem(It.IsAny()))
+ .Callback((T item) => itemsToPut.Add(item));
+
+ batchWrite.
+ Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var item in itemsToPut)
+ {
+ inMemoryTable.Add(item);
+ }
+
+ itemsToPut.Clear();
+ });
+
+ return batchWrite.Object;
+ }
+
+ public IMultiTableBatchWrite CreateMultiTableBatchWriteMock()
+ {
+ var multiBatchWrite = new Mock();
+ var batches = new List();
+
+ multiBatchWrite
+ .Setup(x => x.AddBatch(It.IsAny()))
+ .Callback((IBatchWrite batch) =>
+ {
+ batches.Add(batch);
+ });
+
+ multiBatchWrite
+ .Setup(x => x.Execute())
+ .Callback(() =>
+ {
+ foreach (var batch in batches)
+ {
+ batch.Execute();
+ }
+ });
+
+ return multiBatchWrite.Object;
+ }
+ }
+}