【问题标题】:Mock CSV DictReader模拟 CSV DictReader
【发布时间】:2015-10-23 21:47:37
【问题描述】:

有没有办法模拟DictReader 进行单元测试,而无需实际编写文件然后重新打开它。

我的函数接受DictReader 实例,因此我可以轻松地传递给它们以测试它们的功能,但如果不打开文件似乎无法获得。

目前我正在手动编写一个 CSV 文件,然后在每次测试时将其删除。

class TestRowsStuff(unittest.TestCase):
    def write_csv(self, path, iterable):
        with open(path, 'wb') as f:
            writer = csv.DictWriter(f, [PP, SN, TN])
            writer.writeheader()
            writer.writerows(iterable)

    def setUp(self):
        ...
        self.test_file = os.path.join('test.csv')
        self.write_csv(self.test_file, test_values)

    def tearDown(self):
        os.remove(self.test_file)

【问题讨论】:

  • 为什么不直接使用内存中的 StringIO 对象来存储/读取文件?

标签: python python-2.7 csv mocking


【解决方案1】:

您可以使用内存中的 StringIO 对象来存储/读取 Unicode/字符串:

In [10]: from StringIO import StringIO

In [11]: import csv

In [12]: csvfile = StringIO()

In [13]: csvfile.seek(0)

# sample taken from [here](https://docs.python.org/2/library/csv.html)    
In [14]: fieldnames = ['first_name', 'last_name']

In [15]: writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

In [16]: writer.writeheader()

In [17]: writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})

In [18]: writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})

In [19]: writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

In [20]: csvfile.seek(0)

回读:

In [21]: csvfile.readlines()
Out[21]: 
['first_name,last_name\r\n',
 'Baked,Beans\r\n',
 'Lovely,Spam\r\n',
 'Wonderful,Spam\r\n']

如果你想使用内存缓冲区,你也可以使用 io.StringIO

【讨论】:

  • 这看起来很有趣。我会试一试。这不是一个超级经常运行的测试,我不得不一遍又一遍地写出文件,这很不方便。
  • 尝试这个时我得到TypeError: expected str, bytes or os.PathLike object, not _io.StringIO;这个答案是为python2写的吗?
【解决方案2】:

如果有人正在寻找模拟 writerow 并想检查数据是否已成功传递给 csv writer:

from unittest import mock

@mock.patch('csv.writer')
def test_csv_writer_writerow(self, csv_writer_mock):
    (do your stuff...)
    csv_writer_mock.writerow.assert_has_calls([mock.call(expected_data_here)])

【讨论】:

    【解决方案3】:

    如果您正在寻找一种计数writerow 的方法,这可能会让人失望

    from mock import Mock, patch
    from where.you.do.stuff import do
    @patch('where.you.do.stuff.csv')
    def test846(self, m_csv):
        m_csv.writer = Mock(writerow=Mock())
        do()
        self.assertEqual(m_csv.writer.call_count, 1)
        self.assertEqual(m_csv.writer().writerow.call_count, 999)
    
    
    
    import csv
    from io import StringIO
    def do():
        w = csv.writer(StringIO)
        for i in range(1, 999):
            w.writerow(i)
    

    【讨论】:

      猜你喜欢
      • 2020-01-27
      • 2023-03-26
      • 2018-02-01
      • 2011-12-14
      • 2010-11-15
      • 2015-12-10
      • 1970-01-01
      • 2016-03-28
      • 1970-01-01
      相关资源
      最近更新 更多