使用无效的unicode初始化`io.StringIO`,以便`.readlines`失败?

时间:2016-12-19 13:23:50

标签: python python-3.x unit-testing

是否可以使用无效的UTF-8字符串初始化io.StringIO(或等效字符串),以便在调用readlines()时失败?我知道这是一个奇怪的请求,但我试图在单元测试中重现失败模式。

目前,我正在尝试阅读文本文件,并且意外地获得了一个二进制文件。我的代码崩溃了

  

builtins.UnicodeDecodeError:'utf-8'编解码器无法解码位置0的字节0x89:无效的起始字节

我想在测试用例中重现这一点,然后解决此问题(捕获UnicodeDecodeError,然后报告该文件无效)。但是,我不想在我的测试用例中保留无效文件的副本。我认为应该可以创建一个类似于文件的对象,其行为类似于我的无效文件实例。

我试过

f = io.BytesIO(b'\x89')
myfunction(f)

但是这不起作用,因为从f读取会返回bytes个对象。我需要一些试图返回str(unicode)的东西。我不能使用像

这样的东西
f = io.StringIO('\x89')
myfunction(f)

因为在调用myfunction之前已经失败了。有什么想法吗?

我目前的解决方法是:

import listingparser
import unittest
import io

class ListingParserTestCase(unittest.TestCase):
    def test_invalid_input(self):
        """ Invalid file contents should cause ParseError, not UnicodeDecodeError. """
        with open('test-temp.dat', 'wb') as f:
            f.write(b'\x89')
        with open('test-temp.dat', 'r') as invalid_file:
            with self.assertRaises(listingparser.ParseError):
                listingparser.parsef(invalid_file)

但是我想做同样的事情 - 创建一个陷阱的invalid_file对象 - 没有临时文件。以下不计算:-),我觉得它需要对parsef的内部结构了解太多:

class MockFile(object):
    def readlines(self):
        raise ParseError()

1 个答案:

答案 0 :(得分:1)

  

但是,我不想在我的测试用例中保留无效文件的副本。

为什么不呢?这是一个测试案例。

>>> import codecs,io
>>> f=codecs.EncodedFile(io.BytesIO(b'\x89'), 'utf-8')
>>> f.readlines()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x89 in position 0: invalid start byte