Aws-sdk-net: Cannot mock DynamoDBContext.CreateBatchGet due to lack of interfaces

Created on 5 Sep 2019  路  4Comments  路  Source: aws/aws-sdk-net


When I try write unit test for code which uses DynamoDBContext.CreateBatchGet I'm stuck on providing fake results. The BatchGet does not have a public available constructor nor does CreateBatchGet use an interface for return type.

Expected Behavior



The easiest way would be to add IBatchGet interface and add it as a return type for CreateBatchGet. This would allow easily provide mock when using IDynamoDbContext and return fake data for my tests.

Current Behavior






BatchGet cannot be instantiated so I'm forced to use concrete type like DynamoDbContext.

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.

Possible Solution



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 :)

Steps to Reproduce (for bugs)





Write unit test which returns fake data from the batch API.

Your Environment

  • AWSSDK.DynamoDBv2 (3.3.101.59)
breaking-change bug moduldynamodb

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).

All 4 comments

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 it. Why does this require a breaking change to fix?

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jefhai picture jefhai  路  5Comments

jc1001 picture jc1001  路  4Comments

ShahriatHossain picture ShahriatHossain  路  4Comments

genifycom picture genifycom  路  4Comments

mihafreenode picture mihafreenode  路  4Comments