Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynamoDB Table misrepresents dependency on IAmazonDynamoDB #1589

Closed
rlyczynski opened this issue Apr 23, 2020 · 17 comments
Closed

DynamoDB Table misrepresents dependency on IAmazonDynamoDB #1589

rlyczynski opened this issue Apr 23, 2020 · 17 comments
Assignees
Labels
dynamodb feature-request A feature should be added or improved. needs-major-version Can only be considered for the next major release p1 This is a high priority issue queued v4

Comments

@rlyczynski
Copy link

rlyczynski commented Apr 23, 2020

I think the Table class misrepresents it's dependency on IAmazonDynamoDB when it really depends on an AmazonDynamoDBClient. The constructor takes an IAmazonDynamoDB but then attempts to cast it to a AmazonDynamoDBClient just a few lines later.

private Table(IAmazonDynamoDB ddbClient, TableConfig config)
{
if (config == null)
throw new ArgumentNullException("config");
if (ddbClient == null)
throw new ArgumentNullException("ddbClient");
#if PCL || UNITY || NETSTANDARD
DDBClient = ddbClient as AmazonDynamoDBClient;
#else
DDBClient = ddbClient;
#endif
Config = config;
}

This hinders the ability to unit test code that relies on the Table class by passing in a mocked version of IAmazonDynamoDB and also makes it very difficult to do something like use a decorator instead of an AmazonDynamoDBClient specifically.

At very least I think the constructor should be clear that it depends on a AmazonDynamoDBClient, but ideally the Table class would really only depended on an IAmazonDynamoDB.

Steps to Reproduce

Use the Table class with an object that implements IAmazonDynamoDB but is not a AmazonDynamoDBClient.

Table.LoadTable((IAmazonDynamoDB)notAnAmazonDynamoDBClient, "tablename")

This will cause the cast to an AmazonDynamoDBClient to fail and set DDBClient to null and eventually result in a NullReferenceException.

@ashishdhingra ashishdhingra added guidance Question that needs advice or information. needs-triage This issue or PR still needs to be triaged. labels Aug 28, 2020
@ashishdhingra
Copy link
Contributor

Hi @rlyczynski,

Good morning.

If you refer the code at

, for platforms PCL || UNITY || NETSTANDARD, the following internal property is declared:

internal AmazonDynamoDBClient DDBClient { get; private set; }

The code at line

DDBClient = ddbClient as AmazonDynamoDBClient;
in Table constructor simple casts to IAmazonDynamoDb to AmazonDynamoDBClient. I'm not sure the design consideration around this, but cast appears to be correct given that there is an internal property of that type.

Hope this provides some guidance.

Thanks,
Ashish

@ashishdhingra ashishdhingra added response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. and removed needs-triage This issue or PR still needs to be triaged. labels Sep 9, 2020
@github-actions
Copy link

This issue has not recieved a response in 2 weeks. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.

@github-actions github-actions bot added the closing-soon This issue will automatically close in 4 days unless further comments are made. label Sep 24, 2020
@Kralizek
Copy link
Contributor

@ashishdhingra

I think this issue is pointing out how accepting a parameter via an interface and then casting it it to a concrete type is a bad practice and malevolent communication. Especially if the constructor throws if the parameter is not of the concrete type.

It gives the false idea one could create a table injecting a fake client (like a mock) and be able to assert the behavior of the class.

Unfortunately, the DynamoDB library is not designed with testing from user side in mind, like this and other issues have highlighted over time.

@ashishdhingra
Copy link
Contributor

@Kralizek Thanks for the input. I understand the concern and will have a developer look at it.

@github-actions github-actions bot removed closing-soon This issue will automatically close in 4 days unless further comments are made. response-requested Waiting on additional info and feedback. Will move to "closing-soon" in 7 days. labels Sep 25, 2020
@ashishdhingra
Copy link
Contributor

Hi @rlyczynski @Kralizek The object is being cast to a AmazonDynamoDBClient to handle NetStandard specific features. The implementation could be handled otherwise to support your request. With that being said, this request will be handled as a feature request to be taken in future sprints, depending on the developers' capacity.

@ashishdhingra ashishdhingra added feature-request A feature should be added or improved. and removed guidance Question that needs advice or information. labels Sep 28, 2020
@william-li-ry
Copy link

Just wondering is there any progress with this issue? I followed the issue from #1801 to here and seems this problem is still not resolved. So what's the current strategy to mock an IAmazonDynamoDB instance? Thanks.

@xero-timothy
Copy link

I'm not affiliated in any way with AWS. But I have to say @rlyczynski, your tone when reporting this issue is unnecessarily aggressive. How about being a good human in the future?

@rlyczynski
Copy link
Author

I'm not affiliated in any way with AWS. But I have to say @rlyczynski, your tone when reporting this issue is unnecessarily aggressive. How about being a good human in the future?

Fair. Was funnier in my head at the time. Definitely come off as a dick as I reread this a year later. My b.

@ericadams
Copy link

@ashishdhingra this is affecting my team's ability to fulfill their test coverage obligations,
and I believe it's been misclassified. It's a #bug and not a #feature-request, given that it's pretty clearly a violation of the public contract declared by IAmazonDynamoDB. After 18months open, do you have a timeline for closing this?

@ashishdhingra
Copy link
Contributor

@ericadams Let me discuss this with the team and post any updates here.

@rlyczynski rlyczynski changed the title I wish you weren't a liar DynamoDB Table misrepresents dependency on IAmazonDynamoDB Sep 14, 2021
@normj
Copy link
Member

normj commented Sep 21, 2021

This is a left over artifact of the Document and DataModel high level abstractions being originally written for .NET Framework and the predominate API used where the sync APIs. These abstractions have some old corners in them that still rely on sync APIs even for .NET Core which the SDK public interface only supports async APIs.

We are trying to prioritize some rework/redesign in these abstractions to remove this old cruft and modernize them. When we do that top of the list is to make sure everything is async only and get rid of this casting.

@Kralizek
Copy link
Contributor

Great to hear @normj

Would it be possible to add in the feature list for the revamp a convenient mocking experience?

Currently, whenever you go higher than the raw client you get stopped by unmockable types.

@sl-omideidivandi
Copy link

i had a look at repo and it looks me that there is not enough Unit tests in DynamodbV2 , the integration tests covers Query Async and etc but no Unit test that we can inspire by :(

@ik130 ik130 added p2 This is a standard priority issue needs-major-version Can only be considered for the next major release and removed p2 This is a standard priority issue labels Dec 1, 2022
@ik130 ik130 added the p1 This is a high priority issue label Dec 1, 2022
@vukovinski
Copy link

Horrible

@ashovlin
Copy link
Member

ashovlin commented Aug 9, 2024

For background, when we moved to versions of .NET that only have an async HTTP client, we removed the sync APIs from the low-level IAmazonDynamoDB.

However we did not remove the sync APIs from the high-level DynamoDB clients, which still rely on the sync low-level APIs. That's why we cast to AmazonDynamoDBClient from the high-level code path, to still access the internal sync APIs that are on AmazonDynamoDBClient but not on IAmazonDynamoDB.

In PR #3388 in the V4 branch, we now delay the cast until right before we need to access the internal, low-level sync APIs.

  • For users still calling the sync high-level APIs in .NET/Standard/Core, you can avoid this by moving to the async equivalents where possible, and then a mocked client should work.
  • If you're still relying on the sync APIs but aren't providing an actual AmazonDynamoDBClient, you'll now see a clearer InvalidOperationException instead of the NullReferenceException from the failed cast.

That's what we have planned currently for V4. In the long term we could explore removing the sync APIs from the high-level library, or else adding back a sync HTTP client support in .NET 5+.

@96malhar
Copy link
Contributor

Hello, we have been working on the V4 of the AWS SDK for .NET. We have added the ability to mock various DynamoDB operations by adding interfaces in both the Data Model mode and Document Model mode in DynamoDB.

Refer to this PR - #3450

The IDynamoDBContext.GetTargetTable methods now return an ITable interface which is implemented the by the Table class. The interface can be mocked to simulate table operations in unit tests.

This feature is available in the AWSSDK.DynamoDBv2 Version 4.0.0-preview.2

Copy link

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dynamodb feature-request A feature should be added or improved. needs-major-version Can only be considered for the next major release p1 This is a high priority issue queued v4
Projects
None yet
Development

No branches or pull requests