2017-02-16 65 views
3

我想了解使用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不是一個函數。那麼我應該使用什麼屬性來替換常量被調用時返回的值呢?

回答

-1

可以的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' 

所以沒必要修補恆定在所有

+0

首先感謝回答我! 是但在這種情況下,這意味着mymodule.MY_CONSTANT的值更改爲所有即將到來的測試。這就是爲什麼我想使用補丁,所以它僅限於我補丁的範圍。 –

+0

然後在你的情況下使用'with patch():'。你還需要什麼?無法理解問題,對不起。 –

+0

在變體#3中,無論如何您都會得到與#2相同的結果,爲什麼您需要類似#3格式的內容? –

0

要回答這個問題從理論上說,我想你會需要修補上,不斷的__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 
相關問題