首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我的班级在我的单元测试中没有被嘲笑?

为什么我的班级在我的单元测试中没有被嘲笑?
EN

Stack Overflow用户
提问于 2021-08-26 10:16:23
回答 1查看 35关注 0票数 0

我正在尝试模拟GetDatabaseConnection,但它仍在运行其中的代码。

代码语言:javascript
复制
class GetDatabaseConnection:
    resp_dict = json.loads(get_secret())
    endpoint = resp_dict.get('host')
    username = resp_dict.get('username')
    password = resp_dict.get('password')
    database_name = resp_dict.get('dbname')
    port = resp_dict.get('port')
    connection = pymysql.connect(host=endpoint, user=username, passwd=password, db=database_name, port=port)
    cursor = connection.cursor()

这是我用来模拟这个类的测试。

代码语言:javascript
复制
    @mock.patch("lambda_function.GetDatabaseConnection")
    def test_mock_simple_class(mock_class):
        mock_class.return_value = "test"

但是我得到了以下错误

代码语言:javascript
复制
test_lambda_function.py::TestPreSignUp::test_mock_simple_class FAILED    [100%]
test_lambda_function.py:151 (TestPreSignUp.test_mock_simple_class)
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/mock.py:1334: in patched
    with self.decoration_helper(patched,
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/contextlib.py:117: in __enter__
    return next(self.gen)
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/mock.py:1316: in decoration_helper
    arg = exit_stack.enter_context(patching)
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/contextlib.py:429: in enter_context
    result = _cm_type.__enter__(cm)
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/mock.py:1389: in __enter__
    self.target = self.getter()
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/mock.py:1564: in <lambda>
    getter = lambda: _importer(target)
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/unittest/mock.py:1236: in _importer
    thing = __import__(import_path)
../lambda_function.py:42: in <module>
    class GetDatabaseConnection():
../lambda_function.py:43: in GetDatabaseConnection
    resp_dict = json.loads(get_secret())
EN

回答 1

Stack Overflow用户

发布于 2021-08-27 09:18:58

您遇到的问题与关于importing without executing the class - python的其他问题中的问题相同。由于您将您的类设计为具有将执行对pymysql的调用的属性,因此即使在刚刚导入文件时(例如,在模拟修补期间),这些属性也会立即执行,甚至不需要创建GetDatabaseConnection的实例。

src.py

代码语言:javascript
复制
import pymysql


class GetDatabaseConnection:
    connection = pymysql.connect(host="127.0.0.1", user='username', passwd="password", db='database_name', port=80)

test_src.py

代码语言:javascript
复制
from unittest import mock

# This will read your class. And this will run your <pymsql> commands even without a running patch yet.
import src  # or <from src import GetDatabaseConnection>


# This will also read your class with or without the import above. And this will run your <pymsql> commands even without the patch yet.
@mock.patch('src.GetDatabaseConnection')
def test_try1():
    assert True

输出

代码语言:javascript
复制
$ pytest -q -rP

================================================================================================= ERRORS ==================================================================================================
______________________________________________________________________________________ ERROR collecting test_samp.py
E   pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1' ([Errno 111] Connection refused)")
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1 error in 0.22s

解决方案1:

通过将类放入类方法中,重新设计类,使其不执行类级别的逻辑。

代码语言:javascript
复制
class GetDatabaseConnection:
    def __init__(self):
        self.connection = pymysql.connect(host="127.0.0.1", user='username', passwd="password", db='database_name', port=80)
代码语言:javascript
复制
from unittest import mock


@mock.patch('src.GetDatabaseConnection')
def test_try(mock_class):
    assert True
代码语言:javascript
复制
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
1 passed in 0.03s

解决方案2:

将您的GetDatabaseConnection转换为普通函数:

代码语言:javascript
复制
def getDatabaseConnection():
    return {
        "connection": pymysql.connect(host="127.0.0.1", user='username', passwd="password", db='database_name', port=80),
    }
代码语言:javascript
复制
from unittest import mock


@mock.patch('src.getDatabaseConnection')
def test_try(mock_func):
    assert True

  • 输出与解决方案1

相同

解决方案3:

不可取。不要在没有运行补丁的情况下直接导入文件。因此,不要为GetDatabaseConnection类打补丁,以避免读取文件和执行pymysql。首先,您需要在导入文件之前修补pymysql。这很难维护,如果您的某个源代码文件导入了包含GetDatabaseConnection类的文件,那么它将会被破坏。

代码语言:javascript
复制
from unittest import mock


@mock.patch('pymysql.connect')
def test_try(mock_pymsql):
    import src  # Or <from src import GetDatabaseConnection>
    print(f"{src.GetDatabaseConnection.connection=}")  # This will be the patched version
    assert True

输出:

代码语言:javascript
复制
$ pytest -q -rP
================================================================================================= PASSES ==================================================================================================
________________________________________________________________________________________________ test_try _________________________________________________________________________________________________
------------------------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------------------------
src.GetDatabaseConnection.connection=<MagicMock name='connect()' id='139647536711760'>
1 passed in 0.03s
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68936673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档