【发布时间】:2014-06-03 17:34:00
【问题描述】:
我有一个接受默认参数的方法:
def build_url(endpoint, host=settings.DEFAULT_HOST):
return '{}{}'.format(host, endpoint)
我有一个测试用例来练习这个方法:
class BuildUrlTestCase(TestCase):
def test_build_url(self):
""" If host and endpoint are supplied result should be 'host/endpoint' """
result = build_url('/end', 'host')
expected = 'host/end'
self.assertEqual(result,expected)
@patch('myapp.settings')
def test_build_url_with_default(self, mock_settings):
""" If only endpoint is supplied should default to settings"""
mock_settings.DEFAULT_HOST = 'domain'
result = build_url('/end')
expected = 'domain/end'
self.assertEqual(result,expected)
如果我在build_url 中删除一个调试点并检查此属性settings.DEFAULT_HOST 将返回模拟值。但是,测试继续失败,并且断言表明 host 的值来自我的实际 settings.py。我知道这是因为 host 关键字参数是在导入时设置的,我的模拟没有被考虑。
调试器
(Pdb) settings
<MagicMock name='settings' id='85761744'>
(Pdb) settings.DEFAULT_HOST
'domain'
(Pdb) host
'host-from-settings.com'
有没有办法在测试时覆盖此值,以便我可以使用模拟的 settings 对象来使用默认路径?
【问题讨论】:
-
确保您正在修补正确的
myapp实例。build_url在哪里定义?您可能需要@patch('module.myapp.settings')而不是@patch(myapp.settings)。 -
是的,调试器中的快速设置表明它正在正确修补(
settings = <magicmock blah blah)。我猜host=settings.DEFAULT_HOST发生在补丁之前。 -
哦,对了。默认是在定义函数时设置的(同样的原因
def foo(x=[])不会在每次调用foo()时给你一个新的空列表)。这导致了一个可能的答案......
标签: python mocking python-unittest