python - 模拟类的构造

标签 python unit-testing mocking

我刚刚开始使用 Python 的 mock库来帮助编写更简洁和独立的单元测试。我的情况是我有一个类可以从非常多毛的格式中读取数据,我想测试这个类上的一个方法,它以干净的方式呈现数据 格式。

class holds_data(object):
    def __init__(self, path):
        """Pulls complicated data from a file, given by 'path'.

        Stores it in a dictionary. 
        """
        self.data = {}
        with open(path) as f:
            self.data.update(_parse(f))

    def _parse(self, file):
        # Some hairy parsing code here
        pass

    def x_coords(self):
        """The x coordinates from one part of the data
        """
        return [point[0] for point in self.data['points']]

上面的代码是对我现有代码的简化。实际上,_parse 是一种相当重要的方法,我在功能级别对其进行了测试。

不过,我希望能够在单元测试级别测试 x_coords。如果我通过给它一个路径来实例化这个类,它会违反 rules of unit tests因为:

A test is not a unit test if:

  • It touches the filesystem

所以,我希望能够为 holds_data 修补 __init__ 方法,然后只需填写 self.data 的部分> x_coords 需要。像这样的东西:

from mock import patch
with patch('__main__.holds_data.__init__') as init_mock:
    init_mock.return_value = None
    instance = holds_data()
    instance.data = {'points':[(1,1),(2,2),(3,4)]}
    assert(instance.x_coords == [1,2,3])

上面的代码有效,但感觉它是以一种相当迂回的方式进行此测试。是否有更惯用的方法来修补构造函数,或者这是正确的方法吗?另外,在我的类或测试中是否存在我遗漏的代码味道?

编辑:需要明确的是,我的问题是在初始化期间,我的类进行了大量数据处理以组织将由 x_coords 之类的方法呈现的数据>。我想知道什么是修补所有这些步骤的最简单方法,而无需提供完整的输入示例。我只想在我控制它使用的数据的情况下测试 x_coords 的行为。

我这里有没有code smell的问题归结为这个问题:

我敢肯定,如果我将 x_coords 重构为一个将 holds_data 作为参数的独立函数,这会更容易。如果“更容易测试 == 更好的设计”成立,那么这就是要走的路。但是,它需要 x_coords 函数来了解更多关于 holds_data 内部的信息,而我通常会对此感到满意。我应该在哪里进行权衡?更简洁的代码还是更简洁的测试?

最佳答案

既然您只对测试一种方法感兴趣,为什么不模拟整个 HoldsData 类并在其上固定 x_coords 方法?

>>> mock = MagicMock(data={'points': [(0,1), (2,3), (4,5)]})
>>> mock.x_coords = HoldsData.__dict__['x_coords']
>>> mock.x_coords(mock)
[0, 2, 4]

这样您就可以完全控制x_coords 输入和输出(通过副作用或返回值)。

注意:在 py3k 中你可以只做 mock.x_coords = HoldsData.x_coords 因为有 no more unbound methods .

这也可以在模拟对象的构造函数中完成:

MagicMock(data={'points': [(0,1), (2,3), (4,5)]}, x_coords=HoldsData.__dict__['x_coords'])

关于python - 模拟类的构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9980962/

相关文章:

unit-testing - 如何在 CI 管道中对使用不属于 git 远程的模型文件的函数进行单元测试?

java - EasyMock 如何捕获被测试方法调用的 void 方法的参数?

java - 如何在单元测试中调用注入(inject)参数的方法?

c# - 如何编写使用 HttpContext 的服务器端单元测试?

python - 如何通过 python click.version_option 装饰器的 Travis CI 测试?

python - 壁虎。 X值不超过一定点

android - 为Android studio中的单元测试配置测试文件夹

unit-testing - Spock模拟返回错误值

python - 波斯语 NLTK

在 ubuntu 中安装 Python pip