python - 在 python 单元测试中模拟类属性的更好方法

标签 python unit-testing mocking python-mock

我有一个定义类属性的基类和一些依赖它的子类,例如

class Base(object):
    assignment = dict(a=1, b=2, c=3)

我想用不同的作业对这个类进行单元测试,例如空字典,单项等。当然这非常简化,不是重构我的类或测试的问题

我想出的(pytest)测试最终是有效的

from .base import Base

def test_empty(self):
    with mock.patch("base.Base.assignment") as a:
        a.__get__ = mock.Mock(return_value={})
        assert len(Base().assignment.values()) == 0

def test_single(self):
    with mock.patch("base.Base.assignment") as a:
        a.__get__ = mock.Mock(return_value={'a':1})
        assert len(Base().assignment.values()) == 1

这感觉相当复杂和 hacky - 我什至不完全理解它为什么起作用(虽然我熟悉描述符)。 mock 是否会自动将类属性转换为描述符?

感觉更合乎逻辑的解决方案不起作用:

def test_single(self):
    with mock.patch("base.Base") as a:
        a.assignment = mock.PropertyMock(return_value={'a':1})
        assert len(Base().assignment.values()) == 1

或者只是

def test_single(self):
    with mock.patch("base.Base") as a:
        a.assignment = {'a':1}
        assert len(Base().assignment.values()) == 1

我尝试过的其他变体也不起作用(作业在测试中保持不变)。

模拟类属性的正确方法是什么?有没有比上述更好/更容易理解的方法?

最佳答案

base.Base.assignment 被简单地替换为 Mock 对象。您通过添加 __get__ 方法使其成为描述符。

这有点冗长,有点不必要;您可以直接设置 base.Base.assignment:

def test_empty(self):
    Base.assignment = {}
    assert len(Base().assignment.values()) == 0

当然,这在使用测试并发时不太安全。

要使用 PropertyMock,我会使用:

with patch('base.Base.assignment', new_callable=PropertyMock) as a:
    a.return_value = {'a': 1}

甚至:

with patch('base.Base.assignment', new_callable=PropertyMock, 
           return_value={'a': 1}):

关于python - 在 python 单元测试中模拟类属性的更好方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22324628/

相关文章:

java - Web开发中的单元测试与集成测试

ARM STM32 的 Ceedling CMock 设置

c# - 替换部分模拟对象中的只读属性

python - 如何将本地时间字符串转换为 UTC?

python - Tiff 中值滤波器导出为单帧 OpenCV Python

javascript - 如何在 Angular JS 投影上对 window.location 进行单元测试分配?

asp.net-mvc - NUnit 中 MbUnit 的行属性?

java - 如何确保在 mockito 中只调用一次模拟对象

python - 导入 matplotlib 失败,在 heroku 上没有名为 _tkinter 的模块

Python Docker API 需要知道 attach(**kwargs) 到容器的语法