我在我的生产代码中使用pathlib.Path.open()和pathlib.Path.unlink()。该工作的unittest。但是我使用两种不同的方法来patch()。一个带有@patch装饰器,另一个带有上下文管理器with mock.patch()。
我只想要这样的@patch。
class MyTest(unittest.TestCase):
@mock.patch('pathlib.Path.unlink')
@mock.patch('pathlib.Path.open')
def test_foobar(self, mock_open, mock_unlink):但真正的代码如下所示
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中。
看起来可能是这样的:
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更容易阅读。
发布于 2022-02-02 19:26:36
为学习目的
问:我现在如何把“开场白”和“mymock_open”结合起来?
答:将side_effect和return_value of mymock_open分配给opener。
@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)但这很难说是可读性的改善。
都使用装饰器
@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。
都使用上下文管理器
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_open与opener是同一个实例。
验证解
对于一个最小的、可重复的示例,validate_csv的示例实现:
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'https://stackoverflow.com/questions/70893660
复制相似问题