我们有一个看起来像这样的课程:
import boto3
import json
import time
import sys
def stop_instances_python(instanceId):
ec2_client = boto3.client('ec2', region_name='us-east-1')
while True:
try:
ec2_client.stop_instances(InstanceIds=[instanceId])
print "EC2 instance: " + instanceId + " stopped"
break
except Exception, e:
if ('RequestLimitExceeded' in str(e)):
print "Request throttled. Sleeping for 15s"
time.sleep(15)
res = ec2_client.describe_instances(InstanceIds=[instanceId])
print "instance state: " + res['Reservations'][0]['Instances'][0]['State']['Name']
try:
ec2_client.stop_instances(InstanceIds=[instanceId])
print "EC2 instance: " + instanceId + " stopped" ## Unable to test this
except Exception, e:
if ('RequestLimitExceeded' in str(e)):
print "Request throttled again. Sleeping for 10s"
time.sleep(10)
else:
print str(e)
sys.exit(1)
else:
print str(e)
sys.exit(1)
我们想为这个类编写单元测试用例。我们使用moto
和mock
来测试大多数行。我们无法通过评论测试该行:# Unable to test this
。这是因为每次发送停止请求时,都会受到限制。我们的测试用例文件如下所示:
from moto import mock_ec2
from moto import mock_sts
from mock import patch
import botocore
import boto3
import mock
from botocore.exceptions import ClientError
orig = botocore.client.BaseClient._make_api_call
def mock_throttling(self, operation_name, kwarg):
if operation_name == 'StopInstances':
parsed_response = {
'Error': {'Code': '500', 'Message': 'RequestLimitExceeded'}}
raise ClientError(parsed_response, operation_name)
return orig(self, operation_name, kwarg)
def mock_throttling_side_effect(self, operation_name, kwarg):
mock_api = mock.Mock()
parsed_response = {'Error': {'Code': '500', 'Message': 'RequestLimitExceeded'}}
if operation_name == 'StopInstances':
mock_api.side_effect = [
ClientError(parsed_response, operation_name),
orig(self, operation_name, kwarg)
]
mock_api()
return orig(self, operation_name, kwarg)
class TestEC2StopInstances:
@mock_ec2
@mock_sts
@patch('time.sleep', return_value=None)
def test_ec2_lambda_handler(self, patched_time_sleep):
from StopInstancesPython import stop_instances_python
client = boto3.client('ec2', region_name='us-east-1')
response = client.run_instances(ImageId='ami-1234567', MinCount=1, MaxCount=1)
instanceId = response['Instances'][0]['InstanceId']
with patch(
'botocore.client.BaseClient._make_api_call',
new=mock_throttling_side_effect):
stop_instances_python(instanceId)
我们尝试同时使用mock_throttling
和mock_throttling_side_effect
。当我们使用mock_throttling
时,StopInstances
API始终会抛出RequestLimitExceeded异常(这是预期的行为)。
当我们使用mock_throttling_side_effect
时,实例会在第一个StopInstances
API调用中停止,并且还会抛出RequestLimitExceeded异常并继续执行无限循环。
有人可以指导我们如何测试此代码的所有行吗?