buh*_*htz 3 python unit-testing mocking python-3.x
我在我的生产代码中使用pathlib.Path.open()and 。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):
Run Code Online (Sandbox Code Playgroud)
但目前真正的代码看起来像这样
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)
Run Code Online (Sandbox Code Playgroud)
从技术上讲,我的问题是我不知道如何mock_open在使用@patch装饰器时添加 CSV 内容。
它可能看起来像这样:
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)
Run Code Online (Sandbox Code Playgroud)
但我的问题的目标是提高代码的可读性和可维护性。使用两个装饰器会减少缩进。恕我直言,选择一种方式(装饰器或上下文管理器)会更容易阅读。
问:现在如何将“opener”和“mymock_open”结合在一起?
A:将side_effect和return_value赋值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)
Run Code Online (Sandbox Code Playgroud)
但这很难说是可读性的提高。
@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)
Run Code Online (Sandbox Code Playgroud)
仅传递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)
Run Code Online (Sandbox Code Playgroud)
请注意,这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'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
931 次 |
| 最近记录: |