Moto¶
Users can test AWS dependent code using the create_moto_fixture.
-
pytest_mock_resources.
create_moto_fixture
(*ordered_actions, region_name='us-east-1', scope='function')¶ Produce a Moto fixture.
Any number of fixture functions can be created. Under the hood they will all share the same moto server.
Note
Each test executes using a different (fake) AWS account through moto. If you create boto3
client
/resource
objects outside of the one handed to the test (for example, in the code under test), they should be sure to use theaws_access_key_id
,aws_secret_access_key
,aws_session_token
, andendpoint_url
given by the<fixturename>.pmr_credentials
attribute.Note
A moto dashboard should be available for debugging while the container is running. By default it would be available at
http://localhost:5555/moto-api/#
(but the exact URL may be different depending on your host/port config.
Consider the following example:
# src/some_module.py
def list_files(s3_client):
return s3_client.list_objects_v2(Bucket="x", Key="y")
A user could test this as follows:
# tests/some_test.py
from pytest_mock_resources import create_moto_fixture
from pytest_mock_resources.fixture.moto import Session
from some_module import list_files
moto = create_moto_fixture()
def test_list_files(moto: Session):
s3_client = moto.client("s3")
files = list_files(s3_client)
assert ...
The test is handed a proxy-object which should functionally act like a boto3.Session object. Namely you would generally want to call .client(…) or .resource(…) on it.
Note
Each test executes using a different (fake) AWS account through moto. If you create
boto3 client
/resource
objects using boto3 directly, outside of the object
handed to your test, you should make sure to pass all the credentials fields into the
constructor such that it targets the correct AWS instance/account.
For example:
import boto3
from pytest_mock_resources import create_moto_fixture
from pytest_mock_resources.fixture.moto import Session
moto = create_moto_fixture()
def test_list_files(moto: Session):
kwargs = moto.pmr_credentials.as_kwargs()
s3_client = boto3.client("s3", **kwargs)
Note
A moto dashboard should be available for debugging while the container is running.
By default it would be available at http://localhost:5555/moto-api/#
(but
the exact URL may be different depending on your host/port config.
Actions¶
Similar to ordered “actions” in other fixtures, moto supports the static creation of certain kinds of objects ahead of the actual test execution as well.
For moto, this represents as physical infrastructure/configuration/objects within the moto “AWS account” being used by your test.
Per the note above, each test executes in a unique moto “AWS account”. This means
that two create_moto_fixture
fixtures with different infrastructure will be
completely distinct and not leak state (either between tests or between fixtures).
Note
we will absolutely accept feedback on additional kinds of supported objects to add, the current set is motivated by internal use, but is certainly not exhaustive.
S3¶
Currently: S3Bucket
, S3Object
These objects help reduce boilerplate around setting up buckets/files among tests.
from pytest_mock_resources import create_moto_fixture, S3Bucket, S3Object
from pytest_mock_resources.fixture.moto import Session
bucket = S3Bucket("test")
moto = create_moto_fixture(
S3Bucket("other_bucket"),
bucket,
bucket.object("test.csv", "a,b,c\n1,2,3"),
)
def test_ls(moto: Session):
resource = moto.resource("s3")
objects = resource.Bucket("test").objects.all()
assert len(objects) == 1
assert objects[0].key == "test.txt"
assert objects[0].get()["Body"].read() == b"a,b,c\n1,2,3"