2017-02-16 3 views
3

Я пытаюсь понять различные способы исправления константы в Python с помощью mock.patch. Моя цель - использовать переменную, определенную в моем классе Test, как значение патча для моей константы.Как исправить константу в Python, используя макет как параметр функции

Я нашел этот вопрос, который объясняет, как пропатчить константу: How to patch a constant in python И этот вопрос, который объясняет, как использовать себя в патче: using self in python @patch decorator

Но из этого 2-й линии, я не могу получить 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

Затем используйте 'с 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 
Смежные вопросы