标签: python-unittest

仅在一个模块中修补方法

例如,我有一些foo.py带有以下代码的 module( ):

import requests

def get_ip():
    return requests.get('http://jsonip.com/').content
Run Code Online (Sandbox Code Playgroud)

和bar.py具有类似代码的模块:

import requests

def get_fb():
    return requests.get('https://fb.com/').content
Run Code Online (Sandbox Code Playgroud)

我只是不明白为什么接下来会发生:

from mock import patch

from foo import get_ip
from bar import get_fb

with patch('foo.requests.get'):
    print(get_ip())
    print(get_fb())
Run Code Online (Sandbox Code Playgroud)

他们两个被嘲笑: <MagicMock name='get().content' id='4352254472'> <MagicMock name='get().content' id='4352254472'> 似乎只修补foo.get_ip方法with patch('foo.requests.get'),但事实并非如此。我知道我可能会bar.get_fb超出with范围进行调用,但在某些情况下,我只在上下文管理器中运行一种调用许多其他方法的方法,并且我只想requests在一个模块中进行修补。有什么办法可以解决这个问题吗?不改变模块中的导入

python python-3.x python-mock python-unittest python-unittest.mock

9
推荐指数
1
解决办法
3163
查看次数

Python 3 单元测试 - 未调用断言记录器

我知道如何断言已生成日志消息,但我似乎无法弄清楚如何断言未生成日志消息。这是我现在的单元测试(已清理)。请注意,XYZ 类将记录器作为参数,并且test_check_unexpected_keys_found按预期通过。

import unittest
import logging

class TestXYZ(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.test_logger = logging.getLogger('test_logger')
        cls.test_logger.addHandler(logging.NullHandler())

    def test_check_unexpected_keys_found(self):
        test_dict = {
            'unexpected': 0,
            'expected1': 1,
            'expected2': 2,
        }
        xyz = XYZ(self.test_logger)
        with self.assertLogs('test_logger', level='WARNING'):
            xyz._check_unexpected_keys(test_dict)

    def test_check_unexpected_keys_none(self):
        test_dict = {
            'expected1': 1,
            'expected2': 2,
        }
        xyz = XYZ(self.test_logger)
        xyz._check_unexpected_keys(test_dict)
        # assert that 'test_logger' was not called ??
Run Code Online (Sandbox Code Playgroud)

我尝试使用 unittest.patch 像这样:

with patch('TestXYZ.test_logger.warning') as mock_logwarn:
    xyz._check_unexpected_keys(test_dict)
    self.assertFalse(mock_logwarn.called)
Run Code Online (Sandbox Code Playgroud)

但我得到

导入错误:没有名为“TestXYZ”的模块
我也尝试了一些变体,但一无所获。

有谁知道如何处理这个?

python logging unit-testing python-3.x python-unittest

8
推荐指数
1
解决办法
2043
查看次数

Python SQLAlchemy 模拟

这是我进行链式数据库查询调用的一种方法。

import math
def get_all_keys():
    db_session = DBSession()
    keys = db_session.query(SomeClass).all()
Run Code Online (Sandbox Code Playgroud)

我应该嘲笑DBSession().query(SomeClass).all()。我尝试了一些,但没有任何效果。这是我的试验。

@patch('app.modules.somemodule.DBSession')
def test_asd(self, DBSession):
    DBSession.execute.query.execute.all.return_value = [1, 2, 3]
    self.assertListEqual(DBSession.query('qwe').all(), [1, 2, 3])
Run Code Online (Sandbox Code Playgroud)

在这次尝试中,如果我尝试打印,DBSession()我会得到一个MagicMock看起来不错的对象。但是当我运行时pytest出现以下错误。

    self = <test_some_module.SomeModuleTests testMethod=test_asd>, DBSession = <MagicMock name='DBSession' id='140028663111976'>

    @patch('app.modules.somemodule.DBSession')
    def test_asd(self, DBSession):
        DBSession.execute.query.execute.all.return_value = [1, 2, 3]
        print(DBSession().query('qwe').all())
>       self.assertListEqual(DBSession.query('qwe').all(), [1, 2, 3])
E       AssertionError: First sequence is not a list: <MagicMock name='DBSession.query().all()' id='140028662649184'>

tests/test_some_module.py:21: AssertionError
Run Code Online (Sandbox Code Playgroud)

好像我在嘲笑时做错了什么。我的错误是什么?我检查了文档。

python unit-testing sqlalchemy python-unittest python-unittest.mock

8
推荐指数
2
解决办法
2万
查看次数

模拟访问公共 GCS 存储桶的结果

我有以下代码:

bucket = get_bucket('bucket-name')
blob = bucket.blob(os.path.join(*pieces))
blob.upload_from_string('test')
blob.make_public()
result = blob.public_url
# result is `<Mock name='mock().get_bucket().blob().public_url`
Run Code Online (Sandbox Code Playgroud)

我想模拟public_url的结果,我的单元测试代码是这样的

with ExitStack() as st:
    from google.cloud import storage
    blob_mock = mock.Mock(spec=storage.Blob)
    blob_mock.public_url.return_value = 'http://'

    bucket_mock = mock.Mock(spec=storage.Bucket)
    bucket_mock.blob.return_value = blob_mock

    storage_client_mock = mock.Mock(spec=storage.Client)
    storage_client_mock.get_bucket.return_value = bucket_mock

    st.enter_context(
        mock.patch('google.cloud.storage.Client', storage_client_mock))
    my_function()
Run Code Online (Sandbox Code Playgroud)

谷歌存储有没有像FakeRedis或moto这样的东西,所以我可以模拟google.cloud.storage.Blob.public_url?

mocking google-api google-cloud-storage python-unittest google-cloud-python

8
推荐指数
1
解决办法
1584
查看次数

Python-当`new`参数不是DEFAULT时,为什么模拟补丁装饰器不会将模拟对象传递给测试函数

在 Python 3.6 中,我unittest.mock.patch用来修补这样的函数:

class SampleTest(TestCase):

    @mock.patch('some_module.f')
    def test_f(self, mocked_f):
        f()
        mocked_f.assert_called()

Run Code Online (Sandbox Code Playgroud)

This passes a mock.MagicMock() as mocked_f and everything works fine. However, when I want to use a custom mock object instead of the default mock.MagicMock() using new argument, the patch decorator does not pass the mocked object to the test_f method. Running this code will raise a TypeError:

class SampleTest(TestCase):

    @mock.patch('some_module.f', new=lambda: 8)
    def test_f(self, mocked_f):
        f()
        mocked_f.assert_called()
Run Code Online (Sandbox Code Playgroud)
TypeError: test_f() missing 1 required positional argument: …
Run Code Online (Sandbox Code Playgroud)

python python-mock python-unittest

8
推荐指数
2
解决办法
2342
查看次数

在类和方法上组合 @mock.patch 时的顺序

当一个方法应该在测试用例中被模拟时,可以@mock.patch在 pythonunittest框架中应用装饰器(参见1):

    class MyTest(TestCase):
        @patch('method2')
        @patch('method1')
        def test_stuff(self, mock_method1, mock_method_2):
            ...
Run Code Online (Sandbox Code Playgroud)

根据文档2,也可以将 用作@mock.patch类装饰器:

    @patch('method2')
    @patch('method1')
    class MyTest(TestCase):
        def test_stuff(self, mock_method_1, mock_method_2):
            ...
Run Code Online (Sandbox Code Playgroud)

因此,将这两种方法结合起来也应该是可能且合理的:

    @patch('method1')
    class MyTest(TestCase):
        @patch('method2')
        def test_stuff(self, mock_method_A, mock_method_B):
            ...
Run Code Online (Sandbox Code Playgroud)

现在我想知道模拟按什么顺序传递给test_stuff. 那么mock_method_A嘲笑method1还是method2?

python unit-testing python-unittest python-unittest.mock

8
推荐指数
1
解决办法
1614
查看次数

Django 在测试时不创建测试数据库

我正在新创建的 Django 项目中运行测试。

通常我希望看到测试运行时创建的测试数据库。所有测试都运行良好,但我发现运行测试时正在使用我的本地数据库(用于运行服务器)。

在错误的数据库中创建了大量多余的数据。如何让我的测试设置再次使用正常的 test_ dabasename设置?

我不确定我做了什么改变才能实现这一点,我完全被难住了。

class TestRest(TestCase):
    def setUp(self):
        ...

    def test_allowed_to_get_list_authenticated(self):
        ....
Run Code Online (Sandbox Code Playgroud)

django unit-testing python-unittest

8
推荐指数
1
解决办法
1345
查看次数

如何在 Python 中对包含数据库调用的方法进行单元测试

我想对包含数据库 (SQL Server) 调用的方法进行单元测试。

我不想让测试连接到实际的数据库。

我使用unittest进行测试,我做了一些研究,似乎Mocking可以做到这一点,但不确定语法。

下面代码中的 select 语句返回一些整数。我猜想模拟将针对代码的“cursor.execute”和“cursor.fetchall()”部分。

from databaselibrary.Db import Db

class RandomClass():

    def __init__(self, database):
        self.database = database # Main DB for inserting data
            
    def check_file_status(self, trimmed_file_data, file_date):
        cursor = self.database.cursor()

        cursor.execute(f"""SELECT DISTINCT query_id
                FROM wordcloud_count
                WHERE date = '{file_date}'""")
        
        queries_in_DB = set(row.query_id for row in cursor.fetchall())

        queries_in_file = set(trimmed_file_data.keys())

        if queries_in_DB == queries_in_file:
            return False
        
        return True
    
    def run(self):
        print("Hello")


if __name__ == "__main__":
    
    connection_string = 'sql://user:password@server/database'
    
    database = Db(connection_string, autocommit=True)
    
    random = RandomClass(database)
    
    random.run()
Run Code Online (Sandbox Code Playgroud)

测试类可能如下所示: …

python sql-server python-3.x python-unittest python-unittest.mock

8
推荐指数
1
解决办法
1万
查看次数

How to mock failed operations with moto, @mock_dynamodb2?

I am currently trying to write unit tests for my python code using Moto & @mock_dynamodb2 . So far it's been working for me to test my "successful operation" test cases. But I'm having trouble getting it to work for my "failure cases".

In my test code I have:

@mock_dynamodb2
class TestClassUnderTestExample(unittest.TestCase):
    def setUp(self):
        ddb = boto3.resource("dynamodb", "us-east-1")
        self.table = ddb.create_table(<the table definition)
        self.example_under_test = ClassUnderTestExample(ddb)

    def test_some_thing_success(self):
        expected_response = {<some value>}
        assert expected_response = self.example_under_test.write_entry(<some value>)

    def test_some_thing_success(self):
        response …
Run Code Online (Sandbox Code Playgroud)

python python-unittest python-unittest.mock moto

8
推荐指数
1
解决办法
9166
查看次数

Assert_used_once_with 需要检查调用中的实例是否具有相同的信息

我正在尝试使用来自unittest.mock的assert_used_once_with https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_ Called_once_with

但我想检查是否已通过正确的属性传递了两个对象实例。

所以在类中我重写了__eq__func:

    def __eq__(self, other):
        return (
            self.id == other.id
            and self.users == other.users
        )
Run Code Online (Sandbox Code Playgroud)

在我这样使用的代码中

        mock_add_user.assert_called_once_with(context_fix, expected_user_obj1, expected_user_obj2, users)

Run Code Online (Sandbox Code Playgroud)

但我不断收到错误,并且测试人员不断比较实例的 repr,如下所示

<app.domain.model.load_md.Load object at 0x10cb7d7d0>
Run Code Online (Sandbox Code Playgroud)
<app.domain.model.load_md.Load object at 0x10cb7d7d0>
Run Code Online (Sandbox Code Playgroud)

我确实需要一种方法来断言对象的实例是否已作为填充了正确属性的函数的参数传递。

python mocking pytest python-unittest

8
推荐指数
1
解决办法
5284
查看次数