pytest 在 Lambda 函数中找不到模块



我有一个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方法不是GETDELETEPUT时返回错误。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')
...

最新更新