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

Better way to mock class attribute in python unit test(在 python 单元测试中模拟类属性的更好方法)
本文介绍了在 python 单元测试中模拟类属性的更好方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

I have a base class that defines a class attribute and some child classes that depend on it, e.g.

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

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

I want to unittest this class with different assignments, e.g. empty dictionary, single item, etc. This is extremely simplified of course, it's not a matter of refactoring my classes or tests

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

The (pytest) tests I have come up with, eventually, that work are

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 是否会自动将类属性转换为描述符?

This feels rather complicated and hacky - I don't even fully understand why it works (I am familiar with descriptors though). Does mock automagically transform class attributes into descriptors?

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

A solution that would feel more logical does not work:

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

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

Other variants that I've tried don't work either (assignments remains unchanged in the test).

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

What's the proper way to mock a class attribute? Is there a better / more understandable way than the one above?

推荐答案

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

base.Base.assignment is simply replaced with a Mock object. You made it a descriptor by adding a __get__ method.

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

It's a little verbose and a little unnecessary; you could simply set base.Base.assignment directly:

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

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

This isn't too safe when using test concurrency, of course.

要使用 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 单元测试中模拟类属性的更好方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

patching a class yields quot;AttributeError: Mock object has no attributequot; when accessing instance attributes(修补类会产生“AttributeError:Mock object has no attribute;访问实例属性时)
How to mock lt;ModelClassgt;.query.filter_by() in Flask-SqlAlchemy(如何在 Flask-SqlAlchemy 中模拟 lt;ModelClassgt;.query.filter_by())
FTPLIB error socket.gaierror: [Errno 8] nodename nor servname provided, or not known(FTPLIB 错误 socket.gaierror: [Errno 8] nodename nor servname provided, or not known)
Weird numpy.sum behavior when adding zeros(添加零时奇怪的 numpy.sum 行为)
Why does the #39;int#39; object is not callable error occur when using the sum() function?(为什么在使用 sum() 函数时会出现 int object is not callable 错误?)
How to sum in pandas by unique index in several columns?(如何通过几列中的唯一索引对 pandas 求和?)