标签: pytest-mock

如何使用pytest-mock或magicmock模拟导入的对象

我正在尝试了解这些mock/monkeypatch/pytest-mock功能。

让我知道是否可行。如果不能,请建议我如何测试此代码。

我的代码结构:

/
./app
../__init__.py
../some_module1
.../__init__.py
../some_module2
.../__init__.py
./tests
../test_db.py
Run Code Online (Sandbox Code Playgroud)

/app/__init__.py此处启动我的应用程序(如果有帮助,则为Flask应用程序),并初始化与MongoDB数据库的数据库连接对象:

# ...

def create_app():
  # ...
  return app

db_conn = DB()
Run Code Online (Sandbox Code Playgroud)

some_module1some_module导入db_conn对象,并把它作为自己的部分功能:

## some_module1/__init__.py
from app import db_conn

...
db = db_conn.db_name2.db_collection2

def some_func1():
    data = db.find()
    # check and do something with data
    return boolean_result

...

## some_module2/__init__.py
from app import db_conn

...
db = db_conn.db_name1.db_collection1

def some_func2():
    data = db.find()
    # check and do something …
Run Code Online (Sandbox Code Playgroud)

python unit-testing mocking pytest pytest-mock

6
推荐指数
1
解决办法
153
查看次数

pytest-mock 补丁上下文管理器在退出时不恢复对象

我们最近从单元测试切换到了 pytest。mocker.patch我在使用上下文管理器时遇到了一个奇怪的问题。考虑以下示例。

模块_a.py

class MyClass:
    def value(self):
        return 10
Run Code Online (Sandbox Code Playgroud)

模块_b.py

import module_a
class AnotherClass:
    def get_value(self):
        return module_a.MyClass().value()
Run Code Online (Sandbox Code Playgroud)

测试模块b.py

from module_b import AnotherClass
def test_main_2(mocker):
    with mocker.patch('module_a.MyClass.value', return_value=20):
        value = AnotherClass().get_value()
        assert value == 20
    value = AnotherClass().get_value()
    assert value == 10
Run Code Online (Sandbox Code Playgroud)

我希望一旦上下文管理器退出,MyClass 的 value method 方法将被恢复(返回值 10),但是测试在第二个断言语句上失败并出现断言错误20 != 10如果我使用完全相同的测试,但替换mocker.patchunittest.mock.patch,它通过。我认为 pytest-mock 与 unittest.mock 共享相同的 API,所以我很困惑为什么会有差异。

python pytest pytest-mock

5
推荐指数
1
解决办法
6489
查看次数

对于函数调用断言,Python pytest 模拟失败并显示“assert None”

我正在尝试模拟对 boto3 的一些调用,看起来被模拟的函数正在返回正确的值,并且看起来如果我更改断言使其不再匹配断言中传递的内容失败,因为输入参数不匹配,但是如果我让它们匹配,那么断言失败:

E       AssertionError: assert None
E        +  where None = <bound method wrap_assert_called_with of <MagicMock name='get_item' id='139668501580240'>>(TableName='TEST_TABLE', Key={'ServiceName': {'S': 'Site'}})
E        +    where <bound method wrap_assert_called_with of <MagicMock name='get_item' id='139668501580240'>> = <MagicMock name='get_item' id='139668501580240'>.assert_called_with
E        +      where <MagicMock name='get_item' id='139668501580240'> = <botocore.client.DynamoDB object at 0x7f071b8251f0>.get_item
E        +        where <botocore.client.DynamoDB object at 0x7f071b8251f0> = site_dao.ddb_client
Run Code Online (Sandbox Code Playgroud)

dynamo DB 对象是一个全局变量。

ddb_client = boto3.client("dynamodb")

def query_ddb():
        """Query dynamo DB for the current strategy.

        Returns:
            strategy (str): The latest strategy from dynamo DB. …
Run Code Online (Sandbox Code Playgroud)

python unit-testing pytest pytest-mock

5
推荐指数
1
解决办法
1582
查看次数

使用 pytest-mock 检查调用顺序

在下面显示的代码片段中,我想测试函数中的函数调用顺序run(),即,在调用之后f_3调用:f_2f_1

class TestMock:

    def f_1(self) -> None:
        pass

    def f_2(self) -> None:
        pass

    def f_3(self) -> None:
        pass

    def run(self) -> None:
        self.f_1()
        self.f_2()
        self.f_3()
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使用 来做到这一点吗pytest-mock?我尝试在测试文件中模拟f_1f_2和函数并使用with ,但是没有成功。f_3assert_has_callsany_order=False

预先感谢您的任何帮助或提示!

最好的,阿列克谢

python mocking pytest pytest-mock

5
推荐指数
1
解决办法
2178
查看次数

`requests_mock` 适用于所有请求,即使它们没有设置并抛出 NoMockAddress 异常

我发现requests_mock用作固定装置pytest适用于所有请求,即使它们没有设置。

我不确定这是一个requests_mock/pytest错误还是我遗漏了一些东西。最终,我不需要模拟“api-b”调用,但我不知道如何避免它。

def test_reqs(requests_mock):
    requests_mock.get('https://api-a.com/')
    requests.get('https://api-b.com/')
    assert requests.get('https://api-a.com/')
Run Code Online (Sandbox Code Playgroud)

我正在使用pytestrequests-mockpytest-mock作为 API 端点编写集成测试。在幕后,这个端点对我需要模拟的不同第三方 API 进行了多次调用。

其中一些调用可以被 嘲笑requests_mock。但其中一些不能,因为它们是从第三方模块内部进行调用的。

我尝试用pytest-mockmock最后一个发现它基本上不起作用。 requests_mock仍在尝试模拟该调用并抛出下一个错误: requests_mock.exceptions.NoMockAddress: No mock address: GET https://api-b.com/

python integration-testing pytest pytest-mock requests-mock

5
推荐指数
1
解决办法
3883
查看次数

Python mock - 修改类属性的模拟类方法

我目前想要测试以下基本 Python 类:

class Example:

    def run_steps(self):
        self.steps = 0

        while self.steps < 4:
            self.step()
    
    def step(self):
        # some expensive API call
        print("wasting time...")
        time.sleep(1000)

        self.steps += 1
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,step() 方法包含一个昂贵的 API 调用,因此我想用另一个函数来模拟它,该函数可以避免昂贵的 API 调用,但仍然会递增self.steps。我发现这样做是可能的(从这里可以看出):

def mock_step(self):
    print("skip the wasting time")
    self.steps += 1

# This code works!
def test(mocker):
    example = Example()
    mocker.patch.object(Example, 'step', mock_step)

    example.run_steps()
Run Code Online (Sandbox Code Playgroud)

我只是创建一个名为 的函数mock_step(self)来避免 API 调用,然后step()用新mock_step(self)函数修补原来的慢速方法。

然而,这导致了新的问题。由于该mock_step(self)函数不是 Mock 对象,因此我无法调用其上的任何 Mock 方法(例如 assert_used() 和 call_count()): …

python unit-testing mocking python-unittest.mock pytest-mock

5
推荐指数
1
解决办法
6567
查看次数

Pytest-mock 未修补类模块中的导入函数

pytest-mock 修补未按预期工作。我的代码:

utils.py

def my_func():
    return 42
Run Code Online (Sandbox Code Playgroud)

classes.py

from utils import my_func

class MyClass:
    def class_method(self):
        return my_func()
Run Code Online (Sandbox Code Playgroud)

test_classes.py

import pytest
from classes import MyClass

def test_myclass(mocker):
    mocker.patch("utils.my_func", return_value=21)
    assert MyClass().class_method() == 21
Run Code Online (Sandbox Code Playgroud)

失败了,返回的是42而不是21

pytest pytest-mock

5
推荐指数
1
解决办法
2162
查看次数

如何用python模拟mongo

如何创建一个模拟的 mongo db 对象来使用 python 测试我的软件?
我尝试了https://pytest-mock-resources.readthedocs.io/en/latest/mongo.html但出现错误。
首先,我尝试了下面的代码:

def insert_into_customer(mongodb_connection):
    collection = mongodb_connection['customer']
    to_insert = {"name": "John", "address": "Highway 37"}
    collection.insert_one(to_insert)


from pytest_mock_resources import create_mongo_fixture
mongo = create_mongo_fixture()

def test_insert_into_customer(mongo):
    insert_into_customer(mongo)

    collection = mongo['customer']
    returned = collection.find_one()

    assert returned == {"name": "John", "address": "Highway 37"}


test_insert_into_customer(mongo)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Traceback (most recent call last):
  File "/home/ehasan-karbasian/Desktop/NationalEliteFoundation/serp_matcher/src/mock_mongo.py", line 19, in <module>
    test_insert_into_customer(mongo)
  File "/home/ehasan-karbasian/Desktop/NationalEliteFoundation/serp_matcher/src/mock_mongo.py", line 11, in test_insert_into_customer
    insert_into_customer(mongo)
  File "/home/ehasan-karbasian/Desktop/NationalEliteFoundation/serp_matcher/src/mock_mongo.py", line 2, in insert_into_customer
    collection = mongodb_connection['customer']
TypeError: 'function' object …
Run Code Online (Sandbox Code Playgroud)

python unit-testing mocking pymongo pytest-mock

5
推荐指数
1
解决办法
1167
查看次数

pytest - 构造函数中的模拟构造函数

全部,

我有一个类似的课程。

from mod import Bar

class Foo:
  def __init__(self):
    self.obj = Bar()
Run Code Online (Sandbox Code Playgroud)

如何Bar使用 pytest / pytest-mock 模拟构造函数?我尝试了以下失败。

def test():
  with mock.patch('mod.Bar') as patched:
    Foo()
Run Code Online (Sandbox Code Playgroud)

pytest python-3.x pytest-mock

4
推荐指数
1
解决办法
2985
查看次数

TypeError:super() 参数 1 必须是类型,而不是 MagicMock - azure-devops python 包

我正在使用 azure-devOps python 模块访问 azure API 以检索一些信息。我已使用以下代码来设置建立连接所需的身份验证。

def retrieve_projects_from_organization(self): 
   credentials = BasicAuthentication('', AZURE_PRIVATE_TOKEN)
   self.azure_connection = Connection(base_url=os.environ.get('AZURE_BASE_URL',''),creds=credentials)
   core_client = self.azure_connection.clients_v6_0.get_core_client()
   project_list = []
   projects_response = core_client.get_projects()
   while projects_response is not None:
     for project in projects_response:
        project_list.append(project)
Run Code Online (Sandbox Code Playgroud)

在编写单元测试用例时,我无法模拟 Connection 类,因为它需要 BasicAuthentication 类型的对象。以下是我的单元测试用例:

def test_retrieve_projects_from_organization(mocker):
    credentials = mocker.patch('msrest.authentication. BasicAuthentication')).return_value
    connection = mocker.patch('azure.devops.connection.Connection').return_value
    core_client = mocker.patch('azure.devops.v6_0.core.CoreClient').return_value
    projects = mocker.patch('azure.devops.v6_0.core.TeamProjectReference').return_value
    connection._creds = type(credentials)
    connection.clients_v6_0.get_core_client.return_value = core_client
    core_client.get_projects.return_value = [projects]

    assert AzureDataFetcher().retrieve_projects_from_organization() == [projects]
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

类型错误:super() 参数 1 必须是类型,而不是 MagicMock

是否有不同的方法来模拟此类或绕过 API 身份验证的方法。

python pytest python-3.x pytest-mock

4
推荐指数
1
解决办法
2965
查看次数