2017-02-16 12 views
3

mock.patchを使用して、Pythonで定数をパッチするさまざまな方法を理解しようとしています。 私の目標は、Testクラスで定義された変数をmy定数のパッチ値として使用できるようにすることです。モックを関数パラメータとして使用してPythonで定数をパッチする方法

Iが一定にパッチを適用する方法について説明し、この問題は検出されませんでした: 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 

私の推測では、mock_MY_CONSTANTは関数ではないので、私は、RETURN_VALUEを使用shoudln'tです。では、定数が呼び出されたときに返される値を置き換えるために使用するはずの属性は何ですか?

答えて

-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 
関連する問題