如何在pytest中使用fudge.patch?nose转pytest的兼容问题
解决pytest与fudge@patch的参数冲突问题
别担心,pytest和fudge并不是不兼容,只是它们的参数处理机制有点小冲突——pytest会默认把测试函数的所有参数都当成fixture来查找,而fudge的@patch装饰器是想把伪造对象直接注入参数里,这就导致了误会。
我之前也遇到过类似的问题,分享几个实用的解决技巧:
技巧1:改用fudge的上下文管理器(最推荐)
放弃装饰器写法,改用with语句来包裹伪造逻辑,这样测试函数不需要额外参数,pytest就不会瞎找fixture了,而且还能保留fudge那种集中设置的优势:
from datetime import datetime from fudge import patch def today(): return datetime.utcnow() def something(): return today() test_time = datetime(2018, 1, 1, 12, 34, 56) def test_something(): with patch('today') as fake_today: fake_today.expects_call().returns(test_time) result = something() assert result == test_time
这种写法和你原来的逻辑完全一致,只是把装饰器换成了上下文管理器,完美避开pytest的fixture检测。
技巧2:把fudge伪造逻辑封装成pytest fixture
如果多个测试都需要用到类似的伪造对象,可以把fudge的逻辑封装成pytest fixture,这样既能复用,又能符合pytest的参数规则:
import pytest from datetime import datetime from fudge import patch def today(): return datetime.utcnow() def something(): return today() test_time = datetime(2018, 1, 1, 12, 34, 56) @pytest.fixture def mocked_today(): with patch('today') as fake: fake.expects_call().returns(test_time) yield fake def test_something(mocked_today): result = something() assert result == test_time
这个方法适合需要重复使用相同伪造规则的场景,而且完全兼容pytest的fixture体系。
为什么nose没问题?
nose的参数解析逻辑和pytest不一样,它允许装饰器直接向测试函数注入参数,不会把所有参数都当成fixture处理,所以你原来的写法在nose里能正常工作。
另外必须说一句,我也特别喜欢fudge这种把调用预期和返回值集中设置的方式,比mock那种拆成好几步的写法直观太多了,你的选择完全没问题😉
内容的提问来源于stack exchange,提问作者quantoid
相关产品推荐
相关产品推荐

