如何断言json.dump是用正确的参数调用的

发布于 2025-02-01 23:57:32 字数 1829 浏览 4 评论 0原文

我正在尝试使用pytest模拟来编写单元测试,该测试正确的参数正在传递给JSON.DUMP

。参数是ids的列表,用于对DB进行查询。对于每个ID 2个调用都可以检索包含相同ID的表。然后将该信息格式化为字典。在列表的末尾,我将最终词典传递给json.dump,这样:

    with open(
        "./src/bloomberg/ecdpmm/bmpmsvc/read/serialize_change_set/serialize_change_set.json",
        "w",
        encoding="utf-8",
    ) as serialized_file:

        json.dump(response_json, serialized_file, default=object_handler, sort_keys=True, indent=4)

让我感到困惑的是,在另一个文件中,我可以写一个测试用例,断言正在传递正确的参数。就像我看过的代码片段一样,这些代码片段按照以下方式进行操作:

json = Mock()

json.loads('{"key": "value"}')
>> <Mock name='mock.loads()' id='4550144184'>

json.loads.assert_called_with('{"key": "value"}')

进行断言是与我的主文件中通过的参数进行比较的参数(我正在模拟的)吗?功能是否高于正确的方法?

任何指导/提示都将不胜感激!

这是我要测试的功能:

def serialize_change_set(change_set_ids: list[int] | None = None) -> None:
    """
    Get a list of altered tables in the change set and serialize them
    """
    logger.info("serialize all the tables in the change set ")

    response_json = {}
    for cs_id in change_set_ids:
        response_json[cs_id] = {"Changed_Tables": {}}

        description = db.get_change_set_description(cs_id)
        response_json[cs_id]["Description"] = description

        altered_tables = db.get_change_set(cs_id)
        for table_name, table_rows in altered_tables.items():
            formatted_rows = [dict(row) for row in table_rows]
            response_json[cs_id]["Changed_Tables"][table_name] = formatted_rows

    with open(
        "serialize_change_set.json",
        "w",
        encoding="utf-8",
    ) as serialized_file:

        json.dump(response_json, serialized_file, default=object_handler, sort_keys=True, indent=4)

I'm attempting to write a unit test using PyTest and Mock that tests that the correct arguments are being passed to json.dump

The function that houses the json.dump accepts 1 argument that is a list of ids that is used to make queries to the db. For each id 2 calls are made to retrieve tables that contain that same id. Then that information is formatted into a dictionary. At the end of the list, I pass the final dictionary to json.dump like so:

    with open(
        "./src/bloomberg/ecdpmm/bmpmsvc/read/serialize_change_set/serialize_change_set.json",
        "w",
        encoding="utf-8",
    ) as serialized_file:

        json.dump(response_json, serialized_file, default=object_handler, sort_keys=True, indent=4)

What confuses me is how, in another file, I can write a test cases asserts the correct arguments are being passed. Like I've seen code snippets that do something along the lines of:

json = Mock()

json.loads('{"key": "value"}')
>> <Mock name='mock.loads()' id='4550144184'>

json.loads.assert_called_with('{"key": "value"}')

When doing the assertion are the arguments (that I am mocking) being compared to the arguments being passed in my main file ? Are the functions above the correct approach to what I am trying to do ?

Any guidance/tips would be greatly appreciated!

Here is the function I am trying to test:

def serialize_change_set(change_set_ids: list[int] | None = None) -> None:
    """
    Get a list of altered tables in the change set and serialize them
    """
    logger.info("serialize all the tables in the change set ")

    response_json = {}
    for cs_id in change_set_ids:
        response_json[cs_id] = {"Changed_Tables": {}}

        description = db.get_change_set_description(cs_id)
        response_json[cs_id]["Description"] = description

        altered_tables = db.get_change_set(cs_id)
        for table_name, table_rows in altered_tables.items():
            formatted_rows = [dict(row) for row in table_rows]
            response_json[cs_id]["Changed_Tables"][table_name] = formatted_rows

    with open(
        "serialize_change_set.json",
        "w",
        encoding="utf-8",
    ) as serialized_file:

        json.dump(response_json, serialized_file, default=object_handler, sort_keys=True, indent=4)

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

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

发布评论

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

评论(2

送你一个梦 2025-02-08 23:57:32

如果您有一个模块(例如my_module.py):

import json


def my_function(response_json):
    with open(
        "serialize_change_set.json",
        "w",
        encoding="utf-8",
    ) as serialized_file:
        json.dump(
            response_json,
            serialized_file,
            sort_keys=True,
            indent=4,
        )

然后,您可以编写这样的测试,以模拟json.dump
然后稍后测试以查看如何称呼它。在test_my_module.py我们中
有:

import my_module
from unittest import mock


def test_my_function():
    test_data = {"some": "value"}

    with mock.patch("my_module.json"), mock.patch(
        "my_module.open", mock.mock_open()
    ) as _open:
        my_module.my_function(test_data)

        my_module.json.dump.assert_called_with(
            test_data, _open(), sort_keys=True, indent=4
        )

我们必须同时模拟json.dump和indentin open函数
(因为(a)我们不希望我们的单元测试创​​建文件,并且(b)我们
希望能够在我们的调用中与Open返回的值匹配
assert_called_with)。


我们的测试通过:

$ pytest -v
========================================== test session starts ==========================================
platform linux -- Python 3.10.4, pytest-6.2.4, py-1.11.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/lars/tmp/python
plugins: anyio-3.5.0
collected 1 item

test_my_module.py::test_my_function PASSED                                                        [100%]

=========================================== 1 passed in 0.02s ===========================================

If you have a module (say, my_module.py) that does this:

import json


def my_function(response_json):
    with open(
        "serialize_change_set.json",
        "w",
        encoding="utf-8",
    ) as serialized_file:
        json.dump(
            response_json,
            serialized_file,
            sort_keys=True,
            indent=4,
        )

Then you can write a test like this that mocks out json.dump and
then later tests to see how it was called. In test_my_module.py we
have:

import my_module
from unittest import mock


def test_my_function():
    test_data = {"some": "value"}

    with mock.patch("my_module.json"), mock.patch(
        "my_module.open", mock.mock_open()
    ) as _open:
        my_module.my_function(test_data)

        my_module.json.dump.assert_called_with(
            test_data, _open(), sort_keys=True, indent=4
        )

We have to mock out both json.dump and the builtin open function
(because (a) we don't want our unit tests to create files, and (b) we
want to be able to match the value returned by open in our call to
assert_called_with).


Our test passing:

$ pytest -v
========================================== test session starts ==========================================
platform linux -- Python 3.10.4, pytest-6.2.4, py-1.11.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/lars/tmp/python
plugins: anyio-3.5.0
collected 1 item

test_my_module.py::test_my_function PASSED                                                        [100%]

=========================================== 1 passed in 0.02s ===========================================
稚然 2025-02-08 23:57:32

iSTM是 json.dump()的争论的最佳测试是通过_ = json.dump(*args,** kwargs)查看是否是否提出例外。

由于两个函数具有相同的内部逻辑,因此 dumps()函数可以用作 dump 的验证器,而无需写入磁盘。

放置是一个验证功能,并使用模拟连接呼叫。

ISTM that the best possible test for arguments to json.dump() is to run them through _ = json.dump(*args, **kwargs) to see if it raises an exception.

Since the two functions have the same internal logic, the dumps() function can serve as a validator for dump without having to write to disk.

Put that is a validation function and use Mock to attach the call.

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