模拟开放函数与mock\u open

2024-09-27 07:22:23 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我想测试一下Django应用程序的业务逻辑:

def parse_sectors_from_csv():
    sectors_csv = open(os.path.join(settings.BASE_DIR, 'sector', 'fixtures', 'sectors.csv'))
    sectors_csv_reader = csv.DictReader(sectors_csv)
    return [
        {
            'model': 'sector.sector',
            'id': index,
            'fields': {
                'name': row.get('Sector'),
                'slug': slugify(row['Sector']),
                'type_id': row.get('Type_Id')
            }
        }
        for index, row in enumerate(sectors_csv_reader, 1)
    ]

我已经测试了它是否存在文件以及是否存在标题行。在

现在我想嘲笑

^{pr2}$

在我的测试.py我写的

with patch('__builtin__.open', mock_open(read_data=sectors_csv_mock), create=True) as m:
        sectors = service.parse_sectors_from_csv()
        print('Sectors:', sectors)
        self.assertEqual(expected_sectors, sectors)

但据我所知,它在打印Sectors: []时将空文件传递给函数

我读了几遍mock氶open dock,还是搞不懂。在

>>> with patch('__main__.open', mock_open(read_data='bibble')) as m:
...     with open('foo') as h: # what's happening here?
...         result = h.read() # here?
...
>>> m.assert_called_once_with('foo') # and here?
>>> assert result == 'bibble'

Tags: csvfromidreadindexhereparseas
2条回答

每当我觉得需要嘲笑时,我首先会问自己 按照以下思路重构代码是可行的:

  1. 在算法上很重要的东西,我可能想进行单元测试 用实际的断言。

  2. 东西太简单了,我要么(a)几乎不需要测试,要么(b)可以 用一个只执行代码的端到端测试进行充分测试 不做任何断言。

例如:

####
# Hardly worth testing.
####

def parse_sectors_from_csv():
    file_path = sectors_file_path()
    with open(file_path) as fh:
        return do_parse_sectors_from_csv(fh)

####
# Easily tested without mocks.
####

def do_parse_sectors_from_csv(fh):
    reader = csv.DictReader(fh)
    return do_parse_sectors_from_csv(reader)

def sectors_file_path():
    return os.path.join(settings.BASE_DIR, 'sector', 'fixtures', 'sectors.csv')

def parse_sectors_from_csv(rows):
    return [
        {
            'model': 'sector.sector',
            'id': index,
            'fields': {
                'name': row.get('Sector'),
                'slug': slugify(row['Sector']),
                'type_id': row.get('Type_Id')
            }
        }
        for index, row in enumerate(rows, 1)
    ]

模仿的第一条规则:不要在定义对象/方法的地方模仿它们,要在使用它们的地方模仿它们。所以不是__builtin__.open,而是my_app.my_file.open

第二,我不知道mock_open是什么,但您可以用普通的模拟方式来完成:

with mock.patch('my_app.my_file.open') as mocked_open:
    mocked_open.return_value = StringIO('foo')

不管怎样,这都有效。在

p.S.

始终在处理文件时使用with

相关问题 更多 >

    热门问题