Em Ae
Em Ae

Reputation: 8704

Record/Revert DynamoDB state for integration testing

I want to write integration testing for my API Gateway which is using DynamoDB as backend. I was wondering if there is a method/framework/libraries which provides flexibility to record DynamoDB state before tests and revert it back to original state after the tests?

Ideally, I want something which can keep track changes made in DynamoDB since the beginning of tests and revert all those changes once the test is completed.

Upvotes: 1

Views: 1949

Answers (2)

mgalala
mgalala

Reputation: 106

as readyornot recommended, i am also using DynamoDBLocal for integration test. I implemented it like with the following concept:-

  1. Add DynamoDBLocal dependency in the dependency management (in my case gradle: testCompile 'com.amazonaws:DynamoDBLocal:1.11.86').
  2. DynamoDBLocal server needs some native files add them to the test resources, you will find them in the extracted files of the lib (sqlite4java-win32-x86.dll, libsqlite4java-linux-i386.so...etc)
  3. In the @Before Setup of the Junit class set java library path with the location of the native libs you placed in step 2. SQLite.setLibraryPath("src/test/resources/location/of/native");

  4. In the setup method as well start the DynamoDB local server with inMemory mode, so you don't need to delete any records after the test finished.

    final String[] localArgs = { "-inMemory" }; DynamoDBProxyServer server=ServerRunner.createServerFromCommandLineArgs(localArgs); server.start(); ddb = AmazonDynamoDBClientBuilder .standard() .withEndpointConfiguration(new EndpointConfiguration("http://localhost:8000", "local")) .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("test", "password"))) .build(); table = createTable(ddb, TABLE_NAME, HASH_KEY_NAME, SORT_KEY_NAME); Create table like that

private CreateTableResult createTable(AmazonDynamoDB ddb, String tableName, String hashKeyName, String sortKeyName) { List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>(); attributeDefinitions.add(new AttributeDefinition(hashKeyName, ScalarAttributeType.S)); attributeDefinitions.add(new AttributeDefinition(sortKeyName, ScalarAttributeType.S)); List<KeySchemaElement> ks = new ArrayList<KeySchemaElement>(); ks.add(new KeySchemaElement(hashKeyName, KeyType.HASH)); ks.add(new KeySchemaElement(sortKeyName, KeyType.RANGE)); ProvisionedThroughput provisionedthroughput = new ProvisionedThroughput(1000L, 1000L); CreateTableRequest request = new CreateTableRequest() .withTableName(tableName) .withAttributeDefinitions(attributeDefinitions) .withKeySchema(ks) .withProvisionedThroughput(provisionedthroughput); return ddb.createTable(request); }

  1. And here is an example of a test method that tests the table metadata @Test public void createTableTest() { TableDescription tableDesc = table.getTableDescription(); assertEquals(TABLE_NAME, tableDesc.getTableName()); assertEquals("[{AttributeName: " + HASH_KEY_NAME + ",KeyType: HASH}, {AttributeName: " + SORT_KEY_NAME + ",KeyType: RANGE}]", tableDesc.getKeySchema().toString()); assertEquals("[{AttributeName: " + HASH_KEY_NAME + ",AttributeType: S}, {AttributeName: " + SORT_KEY_NAME + ",AttributeType: S}]", tableDesc.getAttributeDefinitions().toString()); assertEquals(Long.valueOf(1000L), tableDesc.getProvisionedThroughput().getReadCapacityUnits()); assertEquals(Long.valueOf(1000L), tableDesc.getProvisionedThroughput().getWriteCapacityUnits()); assertEquals("ACTIVE", tableDesc.getTableStatus()); assertEquals("arn:aws:dynamodb:ddblocal:000000000000:table/" + TABLE_NAME, tableDesc.getTableArn()); ListTablesResult tables = ddb.listTables(); assertEquals(1, tables.getTableNames().size()); }

    1. implement @After method so it deletes the table and shutdown the server

    @After public void tearDown() { ddb.deleteTable(TABLE_NAME); ddb.shutdown(); }

Upvotes: 0

readyornot
readyornot

Reputation: 2863

I use DynamoDB Local in my test environment, instead of running tests against DynamoDB directly. This saves costs and time. I use a test framework (RSpec) where I can delete anything stored in the database after a test is run. http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html

If you need to run tests against a real DynamoDB table, look into DynamoDB streams + AWS Lambda. You can write a Lambda function that is triggered on item changes from your table. That function can, for example, store a record of the change in another table. Once your test is done, it can kick off a second Lambda function which goes through the change table and reverts each change in your original table. http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html

Upvotes: 1

Related Questions