【问题标题】:mock_s3 decorating pytest fixturemock_s3 装饰 pytest 夹具
【发布时间】:2017-06-23 10:04:04
【问题描述】:

我想知道为什么 mock_s3 装饰器在用作 pytest 夹具的装饰器时不起作用。 test_with_fixture 在提供与 test_without 夹具相同的代码时失败。好吧,“相同”,因为它被明确地装饰。

test_with_fixture 引发 AccessDenied 错误,但在这种情况下与 S3 错误的类型无关。问题是,client.list_objects 在使用夹具的测试中没有被模拟。

pytest - 3.1.2
摩托 - 1.0.1
boto3 - 1.0.4

import pytest
import boto3

from moto import mock_s3

BUCKET = 'Foo'


@pytest.fixture()
@mock_s3
def moto_boto():
    res = boto3.resource('s3')
    res.create_bucket(Bucket=BUCKET)


def test_with_fixture(moto_boto):
    client = boto3.client('s3')
    client.list_objects(Bucket=BUCKET)


@mock_s3
def test_without_fixture():     
    res = boto3.resource('s3')
    res.create_bucket(Bucket=BUCKET)

    client = boto3.client('s3')
    client.list_objects(Bucket=BUCKET)

【问题讨论】:

    标签: python mocking pytest boto3 moto


    【解决方案1】:

    另一种方法是使用“自动使用”测试夹具,您可以在其中启动和停止 moto 服务器并创建您的测试存储桶。

    这是基于 mikegrima 对 https://github.com/spulec/moto/issues/620 的评论。

    import pytest
    import boto3
    
    from moto import mock_s3
    
    BUCKET = 'Foo'
    
    
    @pytest.fixture(autouse=True)
    def moto_boto():
        # setup: start moto server and create the bucket
        mocks3 = mock_s3()
        mocks3.start()
        res = boto3.resource('s3')
        res.create_bucket(Bucket=BUCKET)
        yield
        # teardown: stop moto server
        mocks3.stop()
    
    
    def test_with_fixture():
        client = boto3.client('s3')
        client.list_objects(Bucket=BUCKET)
    

    【讨论】:

      【解决方案2】:

      你的fixture的问题是你以后没有使用它,尽管它在你的测试签名test_with_fixture(moto_boto)中。我建议您创建一个夹具,该夹具返回一个可以在您的测试中实例化的函数,以创建您的测试所需的模拟对象(s3 存储桶)。这种实现的一个例子如下:

      import pytest
      import boto3
      
      from moto import mock_s3
      
      BUCKET = 'Foo'
      
      @pytest.fixture()
      def moto_boto():
          @mock_s3
          def boto_resource():
              res = boto3.resource('s3')
              res.create_bucket(Bucket=BUCKET)
              return res
          return boto_resource
      
      @mock_s3
      def test_with_fixture(moto_boto):
              moto_boto()
              client = boto3.client('s3')
              client.list_objects(Bucket=BUCKET)
      

      在这种情况下,我通过夹具和测试中的装饰器使用 moto 库,但上下文管理器可以类似地使用,如 moto README 中所述

      【讨论】:

      • 那么即使使用夹具又有什么意义呢?您可以只导入 moto_boto 函数并在测试中首先执行它。固定装置的优点是可以进行设置和拆卸。在这种情况下,yield 是正确的方法,因为您的夹具设置了模拟,返回到测试上下文,并且只有在测试结束后才会拆除。这就是我们想要的,你可以使用fixture + start() + yield + stop(),或者更好的是fixture + context manager + yield
      【解决方案3】:

      使用上下文管理器:

      import pytest
      import boto3
      
      from moto import mock_s3
      
      BUCKET = 'Foo'
      
      
      @pytest.fixture()
      def moto_boto():
          with mock_s3():
              res = boto3.resource('s3')
              res.create_bucket(Bucket=BUCKET)
              yield
      
      
      def test_with_fixture(moto_boto):
          client = boto3.client('s3')
          client.list_objects(Bucket=BUCKET)
      
      

      使用上下文管理器,startstop 在后台被调用。

      【讨论】:

        猜你喜欢
        • 2022-01-09
        • 2014-09-23
        • 1970-01-01
        • 2022-01-08
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        • 2019-07-13
        • 1970-01-01
        相关资源
        最近更新 更多