[英]How to mock config variables in python3?
這是一個 AWS lambda function
#service.py
from configs import SENDER, DESTINATIONS
from constants import LOG_FORMAT
import logging
def send_mail(body, SENDER, DESTINATIONS):
...
...
在配置文件中,它從 AWS 參數存儲中檢索數據
# 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 文件。 因此它需要 sec 憑據才能調用 AWS。 作為解決方案,我嘗試了 mocking SENDER 和 DESTINATIONS。 但它拋出我錯誤(期待安全令牌)
我希望單元測試獨立於安全令牌。 建議解決方案
發生這種情況是因為當您通過from configs import SENDER, DESTINATION
導入configs.py時,它會自動運行那些調用load_parameters
的語句,即使還沒有活動的模擬/補丁,這些語句又會調用 AWS SSM。
嘗試重構configs.py ,使變量的設置只發生在顯式調用時(而不是導入時)。 最簡單的實現是這樣的:
配置.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),
}
這需要進行一些重構,因為必須在 AWS Lambda function 調用的開頭插入對get_params
的調用。 這樣,調用load_parameters
又使用 AWS SSM 的調用將不會自動執行,我們可以在調用之前准備我們的模擬/補丁。
當還沒有活動的模擬/補丁時,不要導入任何會依次導入configs.py的文件。 首先修補load_parameters
,使其不連接到實際的 AWS SSM。 您可以手動修補它,也可以使用來自moto的裝飾器@mock_ssm
。 只有這樣我們才能安全地導入文件。
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(...)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.