这是一个AWS lambda函数
#service.py
from configs import SENDER, DESTINATIONS
from constants import LOG_FORMAT
import logging
def send_mail(body, SENDER, DESTINATIONS):
...
...在配置文件中,它从AWS param存储中检索数据
# configs.py
from handlers.ssm_handler import load_parameters
from common import constants
import os
environment = os.environ.get(constants.ENVIRONMENT)
JSON_BUCKET = load_parameters(constants.OT_ARCHIVAL_PREFIX+environment+constants.MIGRATION_BUCKET)
SENDER = load_parameters(constants.OT_ARCHIVAL_PREFIX+environment+constants.MAIL_SENDER)
DESTINATIONS = load_parameters(constants.OT_ARCHIVAL_PREFIX+environment+constants.MAIL_DESTINATIONS)
...所以当我试着测试它
# test_service.py
from unittest import TestCase, main, mock
from service import send_mail
class TestMailService(TestCase):
def test_service(self):
with mock.patch('service.SENDER', 'abc@sys.com') as mocked_sender:
with mock.patch('service.DESTINATIONS', 'def@sys.com') as mocked_sender:
with mock.patch('service.logging.Logger.info') as mocked_logging:
send_mail(...)
mocked_logging.assert_called_with('mail sent Successfully')当我导出AWS安全凭据时,此测试用例正在传递。但如果我不通过认证的话就不会了.我猜是因为在service.py文件中,它打开了整个config.py文件。因此,要调用AWS,就需要使用sec证书。作为一种解决方案,我尝试过嘲笑发送者和目的地。但是它抛出了错误(期望安全令牌)
我希望单元独立于安全令牌。提出解决办法
发布于 2021-09-28 13:08:19
这是因为当您导入configs.py (例如通过from configs import SENDER, DESTINATION )时,它会自动运行那些调用load_parameters的语句,这些语句反过来调用AWS,即使还没有活动的模拟/补丁程序。
解决方案1
尝试重构configs.py,使变量的设置只发生在显式调用(而不是导入时)。最简单的实现是这样的:
configs.py
import os
from common import constants
from handlers.ssm_handler import load_parameters
def get_params():
environment = os.environ.get(constants.ENVIRONMENT)
return {
"SENDER": load_parameters(constants.OT_ARCHIVAL_PREFIX+environment+constants.MAIL_SENDER),
"DESTINATIONS": load_parameters(constants.OT_ARCHIVAL_PREFIX+environment+constants.MAIL_DESTINATIONS),
}这需要一些重构,因为对get_params的调用必须在AWS函数调用开始时插入。这样,使用AWS的load_parameters调用就不会自动执行,我们可以在调用它之前准备模拟/补丁。
解决方案2
当还没有活动的模拟/修补程序时,不要导入任何反过来会导入configs.py的文件。首先修补load_parameters,这样它就不会连接到实际的AWS。您可以手动修补它,也可以使用来自莫托的装饰器莫托。只有这样,我们才能安全地导入文件。
from unittest import TestCase, main, mock
from moto import mock_ssm
# from service import send_mail # REMOVE THIS IMPORT!
@mock_ssm # Option 1. Requires <pip install moto>. You have to setup SSM first as usual.
def test_service(mocker): # Requires <pip install pytest-mock>
mocker.patch('handlers.ssm_handler.load_parameters') # Option 2
# with mock.patch('handlers.ssm_handler.load_parameters') as mock_ssm: # Option 3. This is equivalent to Option 2.
mocker.patch('service.SENDER', 'abc@sys.com')
mocker.patch('service.DESTINATIONS', 'def@sys.com')
from service import send_mail # Import it here after the patches have taken effect
send_mail(...)https://stackoverflow.com/questions/69359854
复制相似问题