{"id":13869,"date":"2020-10-19T03:59:58","date_gmt":"2020-10-19T07:59:58","guid":{"rendered":"https:\/\/qxf2.com\/blog\/?p=13869"},"modified":"2020-10-19T03:59:58","modified_gmt":"2020-10-19T07:59:58","slug":"how-to-use-moto-with-aws-dynamodb","status":"publish","type":"post","link":"https:\/\/qxf2.com\/blog\/how-to-use-moto-with-aws-dynamodb\/","title":{"rendered":"How to use moto with AWS DynamoDB"},"content":{"rendered":"<p>Do you want to test the function that uses AWS resources like DynamoDB? The Python <a href=\"https:\/\/pypi.org\/project\/moto\/\">moto<\/a> module is very useful while patching AWS resources. This post will take you through, how we can mock DynamoDB with the help of moto. Here, we will be mocking a method that stores input data into a given DynamoDB table. The idea would be the same for mocking other AWS resources like SQS etc.<\/p>\n<hr \/>\n<h3>Why do we need mocking<\/h3>\n<p>You can skip this section if you are familiar with the term mock. Mock is something like making a simulation, replica, or copy of anything. Let&#8217;s suppose you have to test a method, inside which another function is calling for fetching few data from somewhere else. So, we can&#8217;t afford that much cost for fetching the data every time for different test cases. Hence, we use mocking, where we can provide different data directly, without fetching it in real. Similarly, there can be more conditions for using mocking as well.<\/p>\n<hr \/>\n<h3>Method that we want to test<\/h3>\n<p>This is a simplest method that is used to write data into AWS DynamoDB table. This method takes data input, table name and then write the given data to the given DynamoDB table. For testing the proper working of the method, we don&#8217;t want to mess with our real DynamoDB table of the application. Hence, we will be creating a dummy table by mocking DynamoDB and will verify our method is working proper or not.<\/p>\n<pre lang=\"python\">def write_into_table(item, table_name):\r\n    dynamodb = boto3.resource('dynamodb')\r\n    table = dynamodb.Table(table_name)\r\n    with table.batch_writer() as batch:\r\n        batch.put_item(Item=item)\r\n<\/pre>\n<p>Let us assume this method is in a file called <code>store_data.py<\/code>.<\/p>\n<hr \/>\n<h3>Using moto&#8217;s @mock_dynamodb2<\/h3>\n<p>The Python moto module is super easy to use for mocking. It provides the @mock_dynamodb2 decorator that mocks out DynamoDB. For writing this one test, we will be using the following steps:<\/p>\n<p>1. Decorate the test method with @mock_dynamodb2<br \/>\n2. Create a DynamoDB resource<br \/>\n3. Create a dummy DynamoDB table<br \/>\n4. Create inputs data for store_data.write_into_table()<br \/>\n5. Call\u00a0store_data.write_into_table()<br \/>\n6. Read the corresponding DynamoDB table<br \/>\n7. Verify that the retrieved data matches the supplied data<\/p>\n<hr \/>\n<h5>1. Decorate the test method with @mock_dynamodb2<\/h5>\n<p>Create a new file called <code>test_write_into_table.py<\/code> and add the following lines:<\/p>\n<pre lang=\"python\">import boto3\r\nfrom moto import mock_dynamodb2\r\nimport store_data\r\n\r\n@mock_dynamodb2\r\ndef test_write_into_table():\r\n    \"Test the write_into_table with a valid input data\"\r\n<\/pre>\n<p>Here, we are ready with the test script skeleton by importing necessary modules &amp; decorating our test method with @mock_dynamodb2.<\/p>\n<h5>2. Create a DynamoDB resource<\/h5>\n<p>Now, within the <code>test_write_into_table()<\/code> method, create an DynamoDB resource like following<\/p>\n<pre lang=\"python\">\r\ndynamodb = boto3.resource('dynamodb')\r\n<\/pre>\n<h5>3. Create a dummy DynamoDB table<\/h5>\n<p>You can create a DynamoDB table using the DynamoDB resource like this<\/p>\n<pre lang=\"python\">table_name = 'test'\r\ntable = dynamodb.create_table(TableName=table_name,\r\n        KeySchema=[{'AttributeName': 'date','KeyType': 'HASH'}],\r\n        AttributeDefinitions=[{'AttributeName': 'date','AttributeType': 'S'}])\r\n<\/pre>\n<p>Here we created a table named &#8216;test&#8217; with primary key &#8216;date&#8217; of type string(&#8216;S&#8217;)<\/p>\n<h5>4. Create inputs for store_data.write_into_table()<\/h5>\n<p>Here, we will create an input data to\u00a0<code>store_data.write_into_table()<\/code>, which will also acts as the expected data after reading.<\/p>\n<pre lang=\"python\">\r\ndata = {'date':'07-Oct-2020','company':'qxf2 services','client':1000}\r\n<\/pre>\n<p>For understanding purpose, we took single data but one can have more as per the requirement. After writing the above data into table, the table will look like as follows:<\/p>\n<table style=\"width: 90%; margin-left: auto; margin-right: auto; border: 1px solid black;\">\n<tbody>\n<tr>\n<th>date<\/th>\n<th>company<\/th>\n<th>client<\/th>\n<\/tr>\n<tr>\n<td style=\"width: 30%; background-color: #804000; color: white; text-align: center;\">07-Oct-2020<\/td>\n<td style=\"width: 30%; background-color: #804000; color: white; text-align: center;\">qxf2 services<\/td>\n<td style=\"width: 30%; background-color: #804000; color: white; text-align: center;\">1000<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5>5. Call store_data.write_into_table()<\/h5>\n<p>At this point, when store_data.write_into_table() is executed, it should store the given input data to the corresponding given table.<\/p>\n<pre lang=\"python\">\r\nstore_data.write_into_table(data,table_name)\r\n<\/pre>\n<h5>6. Read the DynamoDB for data<\/h5>\n<p>Let&#8217;s read the data by passing &#8216;date&#8217; as the primary key. Note that we will gonna get a dictionary with a couple of keys, so for getting our data we have to fetch the value of &#8216;Item&#8217; key.<\/p>\n<pre lang=\"python\">\r\nresponse = table.get_item(Key={'date':data['date']})\r\nactual_output = response['Item']\r\n<\/pre>\n<h5>7. Verify that the retrieved data matches the supplied data<\/h5>\n<p>Let&#8217;s assert that the body of the data is same as we stored<\/p>\n<pre lang=\"python\">\r\nassert actual_output == data\r\n<\/pre>\n<hr \/>\n<h3>Combining everything<\/h3>\n<p>Here is how our test looks like :<\/p>\n<pre lang=\"python\">\"\"\"\r\nExample of using moto to mock out DynamoDB table\r\n\"\"\"\r\n\r\nimport boto3\r\nfrom moto import mock_dynamodb2\r\nimport store_data\r\n\r\n@mock_dynamodb2\r\ndef test_write_into_table():\r\n    \"Test the write_into_table with a valid input data\"\r\n    dynamodb = boto3.resource('dynamodb')\r\n    table_name = 'test'\r\n    table = dynamodb.create_table(TableName=table_name,\r\n            KeySchema=[{'AttributeName': 'date','KeyType': 'HASH'}],\r\n            AttributeDefinitions=[{'AttributeName': 'date','AttributeType': 'S'}])\r\n    data = {'date':'07-Oct-2020','company':'qxf2 services','client':1000}\r\n    store_data.write_into_table(data,table_name)\r\n    response = table.get_item(Key={'date':data['date']})\r\n    actual_output = response['Item']\r\n    assert actual_output == data\r\n<\/pre>\n<hr \/>\n<p>Here, we have completed with the simplest approach to use <a href=\"https:\/\/pypi.org\/project\/moto\/\">moto<\/a> with AWS DynamoDB. In similar manner one can use moto for mocking other AWS resources like SQS etc. I hope this post helps you to understand, the concept of mocking DynamoDB with moto.<\/p>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>Do you want to test the function that uses AWS resources like DynamoDB? The Python moto module is very useful while patching AWS resources. This post will take you through, how we can mock DynamoDB with the help of moto. Here, we will be mocking a method that stores input data into a given DynamoDB table. The idea would be [&hellip;]<\/p>\n","protected":false},"author":35,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[177,261,251,249,66],"tags":[],"class_list":["post-13869","post","type-post","status-publish","format-standard","hentry","category-aws","category-aws-dynamodb-aws","category-boto3","category-moto","category-unit-testing"],"_links":{"self":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/13869","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/comments?post=13869"}],"version-history":[{"count":31,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/13869\/revisions"}],"predecessor-version":[{"id":13966,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/posts\/13869\/revisions\/13966"}],"wp:attachment":[{"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/media?parent=13869"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/categories?post=13869"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/qxf2.com\/blog\/wp-json\/wp\/v2\/tags?post=13869"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}