错误:找不到:(使用Moto,Boto3和Python进行python测试没有名称

发布于 2025-01-24 02:39:02 字数 5090 浏览 5 评论 0原文

目前,在我的本地计算机上的Python文件上运行测试很难将其部署到AWS(我只想在本地计算机上运行测试)。

使用Unitest,Boto3,Moto和Pytest实施了测试。

2个文件包含在同一目录中,称为

正在测试的主文件(lambda_function.py) 测试文件(test_api_login.py)

查看错误输出 编辑

/usr/bin/python3 "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --target test_api_login.py::test_login_to_api
Testing started at 12:24 PM ...
Launching pytest with arguments test_api_login.py::test_login_to_api --no-header --no-summary -q in /Users/myk/Documents/DUMP/apiLogin

============================= test session starts ==============================
collecting ... collected 1 item

test_api_login.py::test_login_to_api::test_my_test FAILED    [100%]
test_api_login.py:16 (test_login_to_api.test_my_test)
moto/core/models.py:118: in wrapper
    result = func(*args, **kwargs)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1322: in patched
    with self.decoration_helper(patched,
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py:113: in __enter__
    return next(self.gen)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1304: in decoration_helper
    arg = exit_stack.enter_context(patching)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py:425: in enter_context
    result = _cm_type.__enter__(cm)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1377: in __enter__
    self.target = self.getter()
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1552: in <lambda>
    getter = lambda: _importer(target)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1224: in _importer
    thing = __import__(import_path)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    import requests
    import json
    
    import boto3
    
    ssm = boto3.client('ssm', region_name="us-east-1")
    base_url_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-base-url"])
>   BASE_URL = base_url_obj['Parameters'][0]['Value']
E   IndexError: list index out of range

lambda_function.py:8: IndexError




============================== 1 failed in 3.28s ===============================

Process finished with exit code 1

请参见要测试的主文件的代码(lambda_function.py)

import requests
import json

import boto3

ssm = boto3.client('ssm', region_name="us-east-1")
base_url_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-base-url"])
BASE_URL = base_url_obj['Parameters'][0]['Value']

username_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-username"])
USERNAME = username_obj['Parameters'][0]['Value']

password_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-password"])
PASSWORD = password_obj['Parameters'][0]['Value']


def lambda_handler(event, context):
    username = USERNAME
    password = PASSWORD

    message = ''
    code = 400

    headers = {"Accept": "application/json", "Content-Type": "application/json"}

    try:
        url = f"{BASE_URL}v0/login"

        data = {"username": username, "password": password}

        r = requests.post(url, headers=headers, data=json.dumps(data))
        message = r.json()

    except Exception as e:
        message += f'An error occurred  {str(e)}'

    if "token" in message:
        token = message['token']
        print("token >> " + token)
        put_response = ssm.put_parameter(
            Name='/prof-svc-int/dev/api-token',
            Value=token,
            Type='String',
            Overwrite=True
        )
        print("put_response >> ", put_response)
        code = 200
    output = OutputObj(code,
                       message)

    json_str = json.dumps(output.__dict__)

    result = json.loads(json_str)

    return result


class OutputObj:
    def __init__(self, statusCode, body):
        self.statusCode = statusCode
        self.body = body

请参阅test文件的代码(test_api_login.py) 编辑

import unittest
from unittest.mock import patch
from moto import mock_ssm


@mock_ssm
@patch("lambda_function.lambda_handler.base_url_obj")
@patch("lambda_function.lambda_handler.BASE_URL")
@patch("lambda_function.lambda_handler.username_obj")
@patch("lambda_function.lambda_handler.USERNAME")
@patch("lambda_function.lambda_handler.password_obj")
@patch("lambda_function.lambda_handler.PASSWORD")
class test_login_to_api(unittest.TestCase):
    @mock_ssm
    def test_my_test(self):

        with patch('lambda_function.lambda_handler') as mock_post:
            mock_post.return_value.statusCode = 200

            out = mock_post
            code = out.code
            self.assertEqual(code, 200)

    if __name__ == "__main__":
        unittest.main()

Currently having difficulty running tests on a python file on my local machine meant to be deployed to AWS(I want to run the tests only on my local machine).

The tests were implemented using unittest, boto3, moto and pytest.

2 files are contained in the same directory called

Main file being tested (lambda_function.py)
Test File (test_api_login.py)

See the errors output
EDITED

/usr/bin/python3 "/Applications/PyCharm CE.app/Contents/plugins/python-ce/helpers/pycharm/_jb_pytest_runner.py" --target test_api_login.py::test_login_to_api
Testing started at 12:24 PM ...
Launching pytest with arguments test_api_login.py::test_login_to_api --no-header --no-summary -q in /Users/myk/Documents/DUMP/apiLogin

============================= test session starts ==============================
collecting ... collected 1 item

test_api_login.py::test_login_to_api::test_my_test FAILED    [100%]
test_api_login.py:16 (test_login_to_api.test_my_test)
moto/core/models.py:118: in wrapper
    result = func(*args, **kwargs)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1322: in patched
    with self.decoration_helper(patched,
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py:113: in __enter__
    return next(self.gen)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1304: in decoration_helper
    arg = exit_stack.enter_context(patching)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py:425: in enter_context
    result = _cm_type.__enter__(cm)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1377: in __enter__
    self.target = self.getter()
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1552: in <lambda>
    getter = lambda: _importer(target)
/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/unittest/mock.py:1224: in _importer
    thing = __import__(import_path)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    import requests
    import json
    
    import boto3
    
    ssm = boto3.client('ssm', region_name="us-east-1")
    base_url_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-base-url"])
>   BASE_URL = base_url_obj['Parameters'][0]['Value']
E   IndexError: list index out of range

lambda_function.py:8: IndexError




============================== 1 failed in 3.28s ===============================

Process finished with exit code 1

See the code for the main file being tested (lambda_function.py)

import requests
import json

import boto3

ssm = boto3.client('ssm', region_name="us-east-1")
base_url_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-base-url"])
BASE_URL = base_url_obj['Parameters'][0]['Value']

username_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-username"])
USERNAME = username_obj['Parameters'][0]['Value']

password_obj = ssm.get_parameters(Names=["/prof-svc-int/dev/api-password"])
PASSWORD = password_obj['Parameters'][0]['Value']


def lambda_handler(event, context):
    username = USERNAME
    password = PASSWORD

    message = ''
    code = 400

    headers = {"Accept": "application/json", "Content-Type": "application/json"}

    try:
        url = f"{BASE_URL}v0/login"

        data = {"username": username, "password": password}

        r = requests.post(url, headers=headers, data=json.dumps(data))
        message = r.json()

    except Exception as e:
        message += f'An error occurred  {str(e)}'

    if "token" in message:
        token = message['token']
        print("token >> " + token)
        put_response = ssm.put_parameter(
            Name='/prof-svc-int/dev/api-token',
            Value=token,
            Type='String',
            Overwrite=True
        )
        print("put_response >> ", put_response)
        code = 200
    output = OutputObj(code,
                       message)

    json_str = json.dumps(output.__dict__)

    result = json.loads(json_str)

    return result


class OutputObj:
    def __init__(self, statusCode, body):
        self.statusCode = statusCode
        self.body = body

See the code for test File (test_api_login.py)
EDITED

import unittest
from unittest.mock import patch
from moto import mock_ssm


@mock_ssm
@patch("lambda_function.lambda_handler.base_url_obj")
@patch("lambda_function.lambda_handler.BASE_URL")
@patch("lambda_function.lambda_handler.username_obj")
@patch("lambda_function.lambda_handler.USERNAME")
@patch("lambda_function.lambda_handler.password_obj")
@patch("lambda_function.lambda_handler.PASSWORD")
class test_login_to_api(unittest.TestCase):
    @mock_ssm
    def test_my_test(self):

        with patch('lambda_function.lambda_handler') as mock_post:
            mock_post.return_value.statusCode = 200

            out = mock_post
            code = out.code
            self.assertEqual(code, 200)

    if __name__ == "__main__":
        unittest.main()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心的憧憬 2025-01-31 02:39:02

导入文件时,对ssm.get_parameters进行了执行。
但是mock_ssm仅在之后开始,并且仅在测试期间处于活动状态。

绝对确定boto3/ssm方法正确模拟的一种方法是在模拟函数内导入lambda_function

@pytest.fixture(scope='function')
    def test_my_test(self, aws_credentials):

        import lambda_function

        with patch('lambda_function.lambda_handler') as mock_post:
            mock_post.return_value.statusCode = 200

            out = lambda_function.lambda_handler()

这将确保呼叫ssm.get_parameters在模拟处于活动状态时执行。

请注意,就目前而言,您仍然会遇到SSM参数不存在的问题。作为测试的一部分,您必须先创建这些参数(使用boto3.client(..)。put_parameter)才能读取。

The call to ssm.get_parameters is executed the moment the file is imported.
But mock_ssm only starts afterwards, and is only active for the duration of the test.

One way to be absolutely sure that the boto3/SSM-methods are mocked correctly, is to import the lambda_function inside the mocked function:

@pytest.fixture(scope='function')
    def test_my_test(self, aws_credentials):

        import lambda_function

        with patch('lambda_function.lambda_handler') as mock_post:
            mock_post.return_value.statusCode = 200

            out = lambda_function.lambda_handler()

This will ensure that the call to ssm.get_parameters is executed while the mock is active.

Note that, as it stands, you'll still run into the problem that the SSM parameters do not exist. As part of your tests, you would have to create these parameters first (using boto3.client(..).put_parameter) before they can be read.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文