首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用相同的语法模拟pathlib.Path.open和pathlib.path.unlink?

如何用相同的语法模拟pathlib.Path.open和pathlib.path.unlink?
EN

Stack Overflow用户
提问于 2022-01-28 12:16:28
回答 1查看 286关注 0票数 2

我在我的生产代码中使用pathlib.Path.open()pathlib.Path.unlink()。该工作的unittest。但是我使用两种不同的方法来patch()。一个带有@patch装饰器,另一个带有上下文管理器with mock.patch()

我只想要这样的@patch

代码语言:javascript
复制
class MyTest(unittest.TestCase):
    @mock.patch('pathlib.Path.unlink')
    @mock.patch('pathlib.Path.open')
    def test_foobar(self, mock_open, mock_unlink):

但真正的代码如下所示

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

class MyTest(unittest.TestCase):
    @mock.patch('pathlib.Path.unlink')
    def test_foobar(self, mock_unlink):
        # simulated CSV file
        opener = mock.mock_open(read_data='A;B\n1;2')

        with mock.patch('pathlib.Path.open', opener):
            result = validate_csv(file_path=pathlib.Path('foo.csv'))
            self.assertTrue(result)

这里的技术问题是,在使用mock_open装饰器时,我不知道如何将CSV内容添加到@patch中。

看起来可能是这样的:

代码语言:javascript
复制
class MyTest(unittest.TestCase):
    @mock.patch('pathlip.Path.open')
    @mock.patch('pathlib.Path.unlink')
    def test_foobar(self, mymock_unlink, mymock_open):
        # simulated CSV file
        opener = mock.mock_open(read_data='A;B\n1;2')

        # QUESTION: How do I bring 'opener' and 'mymock_open'
        # together now?

        result = validate_csv(file_path=pathlib.Path('foo.csv'))
        self.assertTrue(result)

但我问题的目标是提高代码的可读性和可维护性。使用两个装饰器可以减少缩进。选择一种方式(装饰者或上下文管理器)将使IMHO更容易阅读。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-02 19:26:36

为学习目的

问:我现在如何把“开场白”和“mymock_open”结合起来?

答:将side_effectreturn_value of mymock_open分配给opener

代码语言:javascript
复制
@mock.patch('pathlib.Path.open')
@mock.patch('pathlib.Path.unlink')
def test_foobar(self, mymock_unlink, mymock_open):
    # simulated CSV file
    opener = mock.mock_open(read_data='A;B\n1;2')

    # QUESTION: How do I bring 'opener' and 'mymock_open'
    # together now?
    mymock_open.side_effect = opener.side_effect    # +
    mymock_open.return_value = opener.return_value  # +

    result = validate_csv(file_path=pathlib.Path('foo.csv'))
    opener.assert_not_called()          # +
    mymock_open.assert_called_once()    # +
    mymock_unlink.assert_called_once()  # +
    self.assertTrue(result)

但这很难说是可读性的改善。

都使用装饰器

代码语言:javascript
复制
@mock.patch('pathlib.Path.open', new_callable=lambda: mock.mock_open(read_data='A;B\n1;2'))  # +
@mock.patch('pathlib.Path.unlink')
def test_foobar(self, mock_unlink, mock_open):
    result = validate_csv(file_path=pathlib.Path('foo.csv'))
    mock_open.assert_called_once()    # +
    mock_unlink.assert_called_once()  # +
    self.assertTrue(result)

传递mock.mock_open(read_data='A;B\n1;2') (作为位置参数new)而不是new_callable=lambda: ...也有效,但是@mock.patch不会将mock_open传递给test_foobar

都使用上下文管理器

代码语言:javascript
复制
def test_foobar(self):
    # simulated CSV file
    opener = mock.mock_open(read_data='A;B\n1;2')

    with mock.patch('pathlib.Path.unlink') as mock_unlink,\
            mock.patch('pathlib.Path.open', opener) as mock_open:  # +
        self.assertIs(mock_open, opener)  # +
        result = validate_csv(file_path=pathlib.Path('foo.csv'))
        mock_open.assert_called_once()    # +
        mock_unlink.assert_called_once()  # +
        self.assertTrue(result)

注意,mock_openopener是同一个实例。

验证解

对于一个最小的、可重复的示例,validate_csv的示例实现:

代码语言:javascript
复制
def validate_csv(file_path):
    """
    :param pathlib.Path file_path:
    :rtype: bool
    """
    with file_path.open() as f:
        data = f.read()
    file_path.unlink()
    return data == 'A;B\n1;2'
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70893660

复制
相关文章

相似问题

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