DynamoDB nodejs Testing Tool
Why?
DynamoDB is a fantastic database, but so far it misses a nice abstraction that would make you more confident that the code you write is correct. All those string-based queries and parameters probably make you uncomfortable, especially if you are coming from the easy-land of MongoDB.
Writing node.js scripts to set tables up and run methods on them quickly gets tiring, without the fantastic workflow that tools like Jest and WallabyJS provide you.
This tool will allow you to iterate quickly while working with DynamoDB.
Take a look at source code with some examples here, or keep reading
How?
We will start the DynamoDB in the background for you (assuming you have Java SDK, if not, you will have to install it). That should also work on CIs!
Locally, we suggest running DynamoDB in the background on port 4567 (run your tests with DYNAMO_TEST_PORT env variables if you want to use a different one) to make things faster.
We dynamically create and delete tables for your tests behind the scenes, to make sure there are no "collisions" or "race conditions".
There is not much API to the library.
You call createTable with an input defined by DynamoDB.CreateTableInput.
That returns an object that has inside two things - the generated name, documentClient which you can use to perform operations.
Example:
Options:
readOnly
We remove tables automatically, even though the names do not collide with each other, DynamoDB starts to slow down with hundreds of tables, especially if they use the same indexes (and they will if you recreate tables with the same shapes over and over).
This method makes the tooling remove the table after all tests in a given file or block are finished.
The use-case is similar to keepTable, but the table will get dynamically recreated from scratch on every test run.
This might be useful in the initial phase when you want to frequently change the table definition and its items.
If you work with a small number of items and you are only concerned about testing reads from a pre-populated table, it's probably best to use this option. It's plenty fast and convenient.
keepTable
If you want to avoid removing tables altogether, pass {keepTable: true} as an option to createTable function.
That option does two things:
- it prevents the tooling from deleting the table
- it allows writing operations on the table the first time around (when the table does not exist or is empty)
- it disables the write operations on the table when the table exists and it has at least one item inside.
This is especially useful if you want to test multiple different ways of querying your dataset, but do not want to wait hundreds of milliseconds or even seconds for the DB to get populated over and over. Imagine inserting a million records to DynamoDB and being able to test different read patterns with wallaby.js. Dream come true!
Example:
Common gotchas
Timeouts
If your CI fails and you see this scary error: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.
or/and this one: TypeError: Cannot read property 'documentClient' of undefined
That means your CI was too slow to startup the DynamoDB. You might need to increase the jest timeout, take a look here: https://jestjs.io/docs/en/jest-object#jestsettimeouttimeout
PreExisting tables
If you see this error: ResourceInUseException: Cannot create preexisting table
that might mean that you are generating the randomName not often enough. For example:
Will not work, because the dynamoSchema object will get defined once, and all calls to createTables will reuse the same name. change it to this:
Let me know if you have any questions or thoughts in the comments below.