使用 unittests 和 moto 模拟 AWS

Using unittests and moto to mock AWS

我习惯于 pytest 单元测试方法,而不使用 classes。今天我想尝试 unittest 并且我想将我的测试封装在 TestCase.

然后考虑这个样本测试class:

import unittest
import moto
import boto3

class TestMyClass(unittest.TestCase):
    @classmethod
    @moto.mock_ssm
    def setUpClass(cls) -> None:
        cls.ssm_client = boto3.client('ssm')
        cls.ssm_client.put_parameter(Name='test', Value='foo', Type='String')

    @moto.mock_ssm
    def test_something(self):
        value = self.ssm_client.get_parameter(Name='test').get('Parameter').get('Value')
        self.assertEqual(value, 'foo')

为什么放置在 setUpClass 中的参数在测试中不可见?我可以想象,通过在那里使用 @moto.mock_ssm 装饰器,一切都将在模拟上下文中完成。

但是,我可以将参数放在 test_something 中,就像:

@moto.mock_ssm
def test_something(self):
    self.ssm_client.put_parameter(Name='test', Value='foo', Type='String')
    value = self.ssm_client.get_parameter(Name='test').get('Parameter').get('Value')
    self.assertEqual(value, 'foo')

然后它(显然)起作用了。为什么不采用我的第一种方法?我不想为每个依赖它的测试填充伪造的 ssm 参数。这样做的最佳方式是什么?

我之所以这么问是因为我要测试的class初始化的时候需要这个参数

模拟装饰器的范围适用于该特定函数,因此在该函数内创建的数据将仅在该函数内可用。

相反,您可以使用 class-装饰器:

import unittest
import moto
import boto3


@moto.mock_ssm
class TestMyClass(unittest.TestCase):

    client = None

    def setUp(self) -> None:
        self.client = boto3.client('ssm')
        self.client.put_parameter(Name='test', Value='foo', Type='String')

    def test_something(self):
        value = self.client.get_parameter(Name='test').get('Parameter').get('Value')
        self.assertEqual(value, 'foo')

请注意,我已切换到 setUp,而不是 setUpClass。因为 setUpClass 是一个 class 方法,它在应用装饰器之前执行,它会尝试对 AWS 本身执行此方法。