20

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

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

pytest - 3.1.2
moto - 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)
4

3 回答 3

14

另一种方法是使用“自动使用”测试夹具,您可以在其中启动和停止 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)
于 2017-12-01T13:18:03.627 回答
8

您的固定装置的问题是您以后没有使用它,尽管它在您的测试签名中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 自述文件中所述

于 2017-06-24T22:20:24.087 回答
8

使用上下文管理器:

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在后台调用。

于 2020-04-14T13:39:26.120 回答