【问题标题】:Trick open() into reading from a non-file?欺骗 open() 从非文件中读取?
【发布时间】:2015-04-28 17:28:09
【问题描述】:

我意识到这是一件很奇怪的事情——主要是为了简化我的单元测试。

我有一个类,它的__init__ 将文件名作为参数,它open()s 并从中读取一堆数据。如果我能以某种方式“欺骗”open() 从字符串对象读取而不是实际将临时文件写入磁盘,那将是非常棒的。

这可能吗?如果可以,我会怎么做?

【问题讨论】:

  • 只需更改__init__的定义即可。其他任何东西(临时文件、替换全局变量或管道)都是可怕的 hack。
  • 如果你真的不能改变__init__(为什么不呢?为什么非单元测试调用者不能轻松地传递任意数据而不是文件名?),这个问题可能是stackoverflow.com/questions/5237693/… 的副本。

标签: python-3.x


【解决方案1】:

您可以在运行测试之前对包含该类的模块进行猴子补丁,并在测试后恢复它:

def my_fake_open(fake_filename):
    return object_with_read_and_close_that_will_feed_correct_data()

def test_something(self):
    module_containing_test.open = my_fake_open
    ...run test...
    del module_containing_test.open

如果您不想编写自己的模拟对象,请查看mock library

【讨论】:

    【解决方案2】:

    阅读速度有点过快,我认为答案应该在io.stringIO 中,它允许您使用字符串的内容创建一个类似文件的对象。

    但是你想要的是一个对象,传递给标准的 open 函数实际上会从你的字符串的内容中产生一个类似文件的对象。

    问题是open 接受一个字符串(或文件描述符),但其他任何东西都会暂停问题。

    所以我不相信这种方法是实用的。

    但实际上,使用tempfile创建文件并不难:

    with tempfile.NamedTemporaryFile() as tmp_file:
        tmp_file.write(your_string)
        yourmodule.YourClass(tmp_file.name)
    

    (如果您在 Windows 上,您可能希望使用 delete=False 并在发送名称以打开它之前关闭。)

    另一种方法可能是只更改 API:如果 init 对名称所做的所有操作都是打开文件,为什么不直接传递类似文件的对象。

    【讨论】:

    • 完全没有帮助。我试图欺骗open() 生成一个实际上由strbytearray 或其他文件系统文件支持的io.stringIO - 出于这个问题的目的,我无法更改我的代码正在打电话。这可能是不可能的,但我想我会问。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 2016-06-07
    • 1970-01-01
    • 2023-03-09
    相关资源
    最近更新 更多