簡體   English   中英

如何使用 moto @mock_dynamodb2 模擬失敗的操作?

[英]How to mock failed operations with moto, @mock_dynamodb2?

我目前正在嘗試使用 Moto 和 @mock_dynamodb2 為我的 python 代碼編寫單元測試。 到目前為止,我一直在測試我的“成功操作”測試用例。 但是我很難讓它為我的“失敗案例”工作。

在我的測試代碼中,我有:

@mock_dynamodb2
class TestClassUnderTestExample(unittest.TestCase):
    def setUp(self):
        ddb = boto3.resource("dynamodb", "us-east-1")
        self.table = ddb.create_table(<the table definition)
        self.example_under_test = ClassUnderTestExample(ddb)

    def test_some_thing_success(self):
        expected_response = {<some value>}
        assert expected_response = self.example_under_test.write_entry(<some value>)

    def test_some_thing_success(self):
        response = self.example_under_test.write_entry(<some value>)
        # How to assert exception is thrown by forcing put item to fail? 

TestClassUnderTestExample 看起來像這樣:

class ClassUnderTestExample:
   def __init__(self, ddb_resource=None):
        if not ddb_resource:
            ddb_resource = boto3.resource('dynamodb')
        self.table = ddb_resource.Table(.....)

   def write_entry(some_value)
        ddb_item = <do stuff with some_value to create sanitized item>        

        response = self.table.put_item(
            Item=ddb_item
        )

        if pydash.get(response, "ResponseMetadata.HTTPStatusCode") != 200:
            raise SomeCustomErrorType("Unexpected response from DynamoDB when attempting to PutItem")

        return ddb_item

在實際模擬 .put_item 操作以返回非成功值時,我完全陷入困境,以便我可以測試 ClassUnderTestExample 是否會按預期處理它並拋出自定義錯誤。 我已經嘗試過在運行測試之前刪除表格之類的事情,但這只會在獲取表格時引發異常,而不是執行帶有錯誤代碼的 PutItem。

我還嘗試為 pydash 或測試上方的表格打上補丁,但我一定是做錯了什么。 我在 moto 的文檔中找不到任何內容。 任何幫助,將不勝感激!

Moto 的目標是完全模仿 AWS 的行為,包括當用戶提供錯誤輸入時的行為。 換句話說,對 AWS 的 put_item() 調用失敗,也會/應該對 Moto 失敗。

沒有內置方法可以強制對有效輸入進行錯誤響應。

從您的示例中很難看出如何強制執行此操作,但看起來值得嘗試使用此行來創建無效輸入:
ddb_item = <do stuff with some_value to create sanitized item>

是的你可以。 為此使用嘲笑 簡單且可運行的示例:

from unittest import TestCase
from unittest.mock import Mock
from uuid import uuid4

import boto3
from moto import mock_dynamodb2


def create_user_table(table_name: str) -> dict:
    return dict(
        TableName=table_name,
        KeySchema=[
            {
                'AttributeName': 'id',
                'KeyType': 'HASH'
            },
        ],
        AttributeDefinitions=[
            {
                'AttributeName': 'id',
                'AttributeType': 'S'
            },
        ],
        BillingMode='PAY_PER_REQUEST'
    )


class UserRepository:
    table_name = 'users'

    def __init__(self, ddb_resource):
        if not ddb_resource:
            ddb_resource = boto3.resource('dynamodb')
        self.table = ddb_resource.Table(self.table_name)

    def create_user(self, username):
        return self.table.put_item(Item={'id': str(uuid4), 'username': username})


@mock_dynamodb2
class TestUserRepository(TestCase):
    def setUp(self):
        ddb = boto3.resource("dynamodb", "us-east-1")
        self.table = ddb.create_table(**create_user_table('users'))
        self.test_user_repo = UserRepository(ddb)

    def tearDown(self):
        self.table.delete()

    def test_some_thing_success(self):
        user = self.test_user_repo.create_user(username='John')
        assert len(self.table.scan()['Items']) == 1

    def test_some_thing_failure(self):
        self.test_user_repo.table = table = Mock()
        table.put_item.side_effect = Exception('Boto3 Exception')

        with self.assertRaises(Exception) as exc:
            self.test_user_repo.create_user(username='John')
            self.assertTrue('Boto3 Exception' in exc.exception)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM