Python中的替身与模拟

0 投票
1 回答
4979 浏览
提问于 2025-04-18 15:36

我想在测试中模拟或者替代一个函数。可能我用的词不太对,如果有错请纠正我。不过我理解模拟是使用像unittest.mock这样的模拟库来创建一个假的对象,并且设定它会接收到什么参数,以及会返回什么结果等等。对我来说,这似乎有点过于复杂,因为我只想让这个模拟或替代的方法返回一个固定的值。

我觉得替代就像是“没有库的模拟”,就像这个问题的答案那样。从我看到的情况来看,这正是我想要的。它简单轻便,不需要在简单的情况下去处理模拟的各种选项。

我的问题是,这样做安全吗?上面的问题似乎是在覆盖一个方法在内存中的表现,这让我觉得不太对劲。这在Python社区被接受吗?还是说总是建议使用一个合适的模拟库?

编辑 如果不在最终块中重新赋值这个方法,会发生什么可怕的事情,就像链接的答案所说的那样?

1 个回答

4

我之所以想自己来模拟这个方法,是因为我不想麻烦去设置一个模拟对象。不过我发现了这篇博客,里面介绍了一种很棒的方法,可以用mock库和注解,这样比手动创建一个Mock实例简单多了。以下是摘录:

rm.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import os.path

def rm(filename):
    if os.path.isfile(filename):
        os.remove(filename)

rmtest.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from mymodule import rm

import mock
import unittest

class RmTestCase(unittest.TestCase):

    @mock.patch('mymodule.os.path')
    @mock.patch('mymodule.os')
    def test_rm(self, mock_os, mock_path):
        # set up the mock
        mock_path.isfile.return_value = False

        rm("any path")

        # test that the remove call was NOT called.
        self.assertFalse(mock_os.remove.called, "Failed to not remove the file if not present.")

        # make the file 'exist'
        mock_path.isfile.return_value = True

        rm("any path")

        mock_os.remove.assert_called_with("any path")

撰写回答