我有一个Lambda,使用SAM CLI创建,只有一个函数。函数本身工作得很好(无论是在本地还是在部署时(,但是pytest
失败了,这表明我的函数无法在我的目录结构中导入模块。
请注意,目录结构显示在问题的底部。
# All commands are run from the 'Lambda' directory.
# With the 'sam' commands, the expected message is returned both locally and when deployed.
sam build -u
sam local invoke MyFunction --event events/405-get.json
sam deploy
# But the 'pytest' command fails.
python -m pytest tests/unit -v
我目前唯一的测试是确保当HTTP方法不是GET
、DELETE
或PUT
时返回错误。from core.exception import MethodNotAllowedException
行实际上位于"my function/app.py"的第2行,如前所述,当在本地运行或部署到AWS时,该函数能够毫无问题地导入此模块。
以下是pytest
遇到的错误。
my-function/app.py:2: in <module>
from core.exception import MethodNotAllowedException
E ModuleNotFoundError: No module named 'core'
我试图将模块移到与"app.py"相同的目录中,但导入仍然失败。
my-function/app.py:2: in <module>
from exception import MethodNotAllowedException
E ModuleNotFoundError: No module named 'exception'
我也尝试使用相对导入,所以我将"myfunction/app.py"的第2行更改为from .core.exception import MethodNotAllowedException
。然而,虽然pytest
现在可以导入模块,但在使用sam local invoke
时,函数本身会失败。因此,我认为相对进口是不可能的。
无法导入模块"app":尝试相对导入,但没有已知的父包
如何让pytest
使用我的函数?
test_handler.py
from proxy import app
import json
import os
import pytest
@pytest.fixture(scope='function')
def mock_context(mocker):
mock_context = mocker.MagicMock()
mock_context.aws_request_id = '00000000-0000-1000-0000-000000000000'
return mock_context
@pytest.fixture(scope='function')
def event(request):
dir = '{0}/../../events'.format(os.path.dirname(os.path.abspath(__file__)))
name = request.param
path = '{0}/{1}'.format(dir, name)
with open(path) as f:
event = f.read()
return event
class TestMethodNotAllowed:
@pytest.mark.parametrize(
'event', ['405-get.json'], indirect=True)
def test_405_get(self, event, mock_context):
'''Test a GET event.'''
response = app.lambda_handler(json.loads(event), mock_context)
body = json.loads(response['body'])
assert response['statusCode'] == 405
assert 'exception' in body
assert 'error_message' in body['exception']
assert body['exception']['error_message'] == 'Method not allowed.'
assert body['exception']['error_type'] == 'MethodNotAllowedException'
assert body['exception']['http_method'] == 'GET'
# Tests for PUT and DELETE also exist.
文件结构
Lambda
├── __init__.py
├── samconfig.toml
├── template.yaml
├── events
| ├── 405-delete.json
| ├── 405-get.json
| └── 405-put.json
├── my-function
| ├── init.py
| ├── app.py
| ├── requirements.txt
| └── core
| ├── __init__.py
| ├── exception.py
| ├── someotherfile.py
| └── morefiles.py
└── test
├── __init__.py
├── requirements.txt
└── unit
├── __init__.py
└── test_handler.py
您可以使用命令行选项(如--import-mode
(控制添加到sys.path
的内容。更多信息,请访问https://docs.pytest.org/en/6.2.x/pythonpath.html.
编辑
如果导入模式不起作用,也许你可以尝试在测试中导入之前自己添加路径,比如
import sys
sys.path.append('../../my-function')
...