在python单元测试中模拟类属性的更好方法 [英] Better way to mock class attribute in python unit test

查看:122
本文介绍了在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

这感觉很复杂而且很笨拙-我什至不完全理解为什么它起作用(尽管我对描述符很熟悉).模拟会自动将类属性转换为描述符吗?

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆