Currently I have a bunch of tests that all send emails via ses:
import boto
from moto import mock_ses
class EmailTestCase(unittest.unitttest):
@mock_ses
def test_some_email_sending_function(self):
conn = boto.connect_ses()
conn = verify_email_identity("[email protected]")
... my test code
Now this works fine, but I find myself "setting up" moto the same way in all of my tests. Is there a recommended way to use moto on a class?
Based on the https://docs.python.org/3.5/library/unittest.mock-examples.html#applying-the-same-patch-to-every-test-method I think something like:
import boto
from moto import mock_ses
@mock_ses
class EmailTestCase(unittest.unitttest):
conn = boto.connect_ses()
conn = verify_email_identity("[email protected]")
def test_some_email_sending_function(self):
... my test code
Would be pretty clean, thoughts?
For this type of thing, I'll usually do something like this
class MyTest(TestCase):
def setUp(self):
self.mock_ses = mock_ses()
self.mock_ses.start()
def test_email_sending(self):
conn = boto.connect_ses()
conn = verify_email_identity("[email protected]")
... my test code
def tearDown(self):
self.mock_ses.stop()
A class-based decorator is a good idea though that I will look into.
@spulec did the class based decorator get implemented? I thought it had at some point because I've even used it in a small project but testing it more vigorously now it doesn't appear to work and was thinking I was doing something wrong but can't find any examples of it being implemented.
@tomeliff Yes, it works pretty well now. I have it in my project like this:
@mock_autoscaling
@mock_ec2
@mock_elb
@mock_elbv2
@mock_iam
@mock_kms
@mock_logs
@mock_rds2
@mock_s3
@mock_sqs
@mock_sts
class BaseTestCase(unittest.TestCase):
Hi @JackDanger,
I tried to do the same :
import boto3
import logging
import unittest
from moto import mock_ec2
@mock_ec2
class TestBackupEbs(unittest.TestCase):
"""
Test class for backupEbs.py
"""
def __init__(self, region='eu-west-1', az='eu-west-1a', log_level='INFO'):
"""
"""
....
self.aws_client = boto3.resource('ec2', region_name=self.region)
......
def test_create_volume_snapshot(self):
"""
This function test create_volume_snapshot.
"""
self.logger.info('Starting test_create_volume_snapshot()')
test_volume_to_backup_tags = [
{
'Key': 'Name',
'Value': 'test_volume_to_backup'
},
{
'Key': 'to_backup',
'Value': 'true'
}
]
self.logger.info('Creating mocked volumes')
test_volume_to_backup = create_ebs_volumes(self.aws_client,self.az, test_volume_to_backup_tags)
self.logger.info('Mocked test_volume_to_backup %s created', test_volume_to_backup.id)
volumes = get_volumes_list(self.aws_client)
create_volume_snapshot(self.aws_client, volumes)
all_snapshots = self.aws_client.snapshots.all()
volume_id_is_correct = False
for snapshot in all_snapshots:
if snapshot.volume_id == test_volume_to_backup.id:
volume_id_is_correct = True
assert volume_id_is_correct
I got the following error :
Failure: ValueError (Invalid endpoint: https://ec2.test_create_volume_snapshot.amazonaws.com) ... ERROR
======================================================================
ERROR: Failure: ValueError (Invalid endpoint: https://ec2.test_create_volume_snapshot.amazonaws.com)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/nose/loader.py", line 523, in makeTest
return self._makeTest(obj, parent)
File "/usr/local/lib/python2.7/site-packages/nose/loader.py", line 570, in _makeTest
return self.loadTestsFromTestCase(obj)
File "/usr/local/lib/python2.7/site-packages/nose/loader.py", line 494, in loadTestsFromTestCase
return super(TestLoader, self).loadTestsFromTestCase(testCaseClass)
File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/loader.py", line 56, in loadTestsFromTestCase
loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
File "/Users/hagerren/Documents/work/gitlab/microservices-infrastructure/paas-orchestration/lambda-functions/functions/backupEbs/tests/test_backupEbs.py", line 29, in __init__
self.aws_client = boto3.resource('ec2', region_name=self.region)
File "/usr/local/lib/python2.7/site-packages/boto3/__init__.py", line 92, in resource
return _get_default_session().resource(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/boto3/session.py", line 389, in resource
aws_session_token=aws_session_token, config=config)
File "/usr/local/lib/python2.7/site-packages/boto3/session.py", line 263, in client
aws_session_token=aws_session_token, config=config)
File "/usr/local/lib/python2.7/site-packages/botocore/session.py", line 861, in create_client
client_config=config, api_version=api_version)
File "/usr/local/lib/python2.7/site-packages/botocore/client.py", line 73, in create_client
verify, credentials, scoped_config, client_config, endpoint_bridge)
File "/usr/local/lib/python2.7/site-packages/botocore/client.py", line 285, in _get_client_args
verify, credentials, scoped_config, client_config, endpoint_bridge)
File "/usr/local/lib/python2.7/site-packages/botocore/args.py", line 79, in get_client_args
timeout=(new_config.connect_timeout, new_config.read_timeout))
File "/usr/local/lib/python2.7/site-packages/botocore/endpoint.py", line 289, in create_endpoint
raise ValueError("Invalid endpoint: %s" % endpoint_url)
ValueError: Invalid endpoint: https://ec2.test_create_volume_snapshot.amazonaws.com
Do you if I miss something ?
Most helpful comment
For this type of thing, I'll usually do something like this
A class-based decorator is a good idea though that I will look into.