問題描述
我有一個定義類屬性的基類和一些依賴它的子類,例如
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 單元測試中模擬類屬性的更好方法的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!