如何使用模拟作为函数参数修补Python中的常量
问题描述:
我想了解使用mock.patch修补Python中常量的不同方法。 我的目标是能够使用在我的测试类定义为我不断修补值的变量。如何使用模拟作为函数参数修补Python中的常量
我发现这个问题,这也解释了如何修补一个常数: How to patch a constant in python 而这个问题解释如何使用自己版本: using self in python @patch decorator
但是从这个第二个环节,我不能得到testTwo方式(提供模拟作为函数参数)工作
这里是我的简单的用例:
我module.py
MY_CONSTANT = 5
def get_constant():
return MY_CONSTANT
test_mymodule.py
import unittest
from unittest.mock import patch
import mymodule
class Test(unittest.TestCase):
#This works
@patch("mymodule.MY_CONSTANT", 3)
def test_get_constant_1(self):
self.assertEqual(mymodule.get_constant(), 3)
#This also works
def test_get_constant_2(self):
with patch("mymodule.MY_CONSTANT", 3):
self.assertEqual(mymodule.get_constant(), 3)
#But this doesn't
@patch("mymodule.MY_CONSTANT")
def test_get_constant_3(self, mock_MY_CONSTANT):
mock_MY_CONSTANT.return_value = 3
self.assertEqual(mymodule.get_constant(), 3)
#AssertionError: <MagicMock name='MY_CONSTANT' id='64980808'> != 3
我的猜测是我shoudln't使用RETURN_VALUE,因为mock_MY_CONSTANT不是一个函数。那么我应该使用什么属性来替换常量被调用时返回的值呢?
答
可以的simpy每个断言之前分配的模拟值不变:
def test_get_constant_3(self):
mymodule.MY_CONSTANT = 3
self.assertEqual(mymodule.get_constant(), 3)
mymodule.MY_CONSTANT = 7
self.assertEqual(mymodule.get_constant(), 7)
有些另一个例子
# --- config.py ---
class AppConf:
APP_TIMEZONE = os.environ.get['APP_TIMEZONE']
# --- my_mod.py ---
from datetime import datetime
from config import AppConf
LOCAL_TZ = AppConf.APP_TIMEZONE
def to_local_tz(dt_obj, tz):
"""Return datetime obj for specific timezone"""
# some code here
return local_dt_obj
def get_local_time():
return to_local_tz(datetime.utcnow(), LOCAL_TZ).strftime('%H:%M')
# --- test_my_mod.py ---
import my_mod
class TestMyMod(unittest.TestCase):
@patch('my_mod.datetime')
def test_get_local_time(self, mock_dt):
# Mock to 15:00 UTC
mock_dt.utcnow.return_value = datetime(2017, 5, 3, 15)
# Test with TZ 'Europe/Kiev' +02:00 +03:00(DST)
my_mod.LOCAL_TZ = 'Europe/Kiev'
assert my_mod.get_local_time() == '18:00'
# Test with TZ 'America/New_York' -05:00 -04:00(DST)
my_mod.LOCAL_TZ = 'America/New_York'
assert my_mod.get_local_time() == '11:00'
所以没必要修补恒定在所有
答
要回答这个问题从理论上说,我想你会需要修补上,不断的__int__()
方法,像这样:
@patch("mymodule.MY_CONSTANT.__int__")
def test_get_constant_4(self, mock_MY_CONSTANT):
mock_MY_CONSTANT.return_value = 3
self.assertEqual(mymodule.get_constant(), 3)
显然,这是错误的方式去了解它,如图它抛出的错误。
AttributeError: 'int' object attribute '__int__' is read-only
首先感谢回答我! 是但在这种情况下,这意味着mymodule.MY_CONSTANT的值更改为所有即将到来的测试。这就是为什么我想使用补丁,所以它仅限于我补丁的范围。 –
然后在你的情况下使用'with patch():'。你还需要什么?无法理解问题,对不起。 –
在变体#3中,无论如何您都会得到与#2相同的结果,为什么您需要类似#3格式的内容? –