When I try write unit test for code which uses DynamoDBContext.CreateBatchGet I'm stuck on providing fake results. The BatchGet
The easiest way would be to add IBatchGet
BatchGet
IAmazonDynamoDB client = Substitute.For<IAmazonDynamoDB>();
IDynamoDBContext context = new DynamoDBContext(client, new DynamoDBOperationConfig
{ OverrideTableName = "Abc" });
BatchGet<T> batch = context.CreateBatchGet<T>();
await batch.ExecuteAsync();
Having this done I strange exceptions from SDK internals like
System.NullReferenceException : Object reference not set to an instance of an object.
at Amazon.DynamoDBv2.DocumentModel.Table.DescribeTable(String tableName)
and still I see no easy way to return results :(
I could do some tweaks in my code by adding some unwanted entity attributes and be able go over this issue but then I'm at executing the batch and still there is no easy way to provide the results. I could do:
IDynamoDBContext context = Substitute.For<IDynamoDBContext>();
BatchGet<T> batch = context.CreateBatchGet<T>();
await batch.ExecuteAsync();
but in this case I cannot find an easy way to provide fake data through the mocked IDynamoDBContext nor mocked IAmazonDynamoDB.
I also cannot return fake data by using another approach
IDynamoDBContext context = Substitute.ForPartsOf<DynamoDBContext>();
BatchGet<T> batch = context.CreateBatchGet<T>(...)
context.ExecuteBatchGetAsync(new BatchGet[] { batch })
because in this case the ExecuteBatchGetAsync public method is not marked as virtual so it's difficult to ovverride that call using eg. NSubstitute.
Add IBatchGet interface for CreateBatchGet in IDynamoDBContext.
(or) Make ExecuteBatchGetAsync virtual in DynamoDBContext
I can provide a pull request for this change if you feel you need one :)
Write unit test which returns fake data from the batch API.
I think it's because of this:
https://github.com/aws/aws-sdk-net/blame/231a7e147159cc8e0da023f35001a25ed923d01e/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs#L378
The as AmazonDynamoDBClient
makes it impossible to pass in a mocked instance for .NET Standard, it will set it to null (which seems like a bug since there are guards to prevent passing in a null in the constructor).
Having the same problem, and found the same issue (essentially): use of the protected version of DescribeTable on AmazonDynamoDBClient instead of the public interface override makes it nonviable to Moq
I also suffer from this issue. Single item operations (LoadAsync / PutAsync) are mockable but their batch counterparts are not which forces us to test against DynamoDB Local. This is not ideal for scenarios.
It has been mentioned here https://github.com/aws/aws-sdk-net/issues/1589 as well.
Most helpful comment
I think it's because of this:
https://github.com/aws/aws-sdk-net/blame/231a7e147159cc8e0da023f35001a25ed923d01e/sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Table.cs#L378
The
as AmazonDynamoDBClient
makes it impossible to pass in a mocked instance for .NET Standard, it will set it to null (which seems like a bug since there are guards to prevent passing in a null in the constructor).