Ответ 1
Декоратору patch
требуется, чтобы цель была полным пунктирным путем, как указано в документации:
target должна быть строка в форме 'package.module.ClassName. Цель импортируется, и указанный объект заменяется новым объектом, поэтому цель должна быть импортируемой из среды, из которой вы вызываете патч. Цель импортируется, когда оформленная функция выполняется, а не время украшения.
"Channel"
- это просто строка, а patch
недостаточно информации для поиска соответствующего класса. Это не то же самое, что имя Channel
, которое вы используете в другом месте, которое импортируется в верхней части модуля.
Второй тест завершился неудачно, потому что канал импортируется в тестовом модуле , а затем патч заменяет Канал в методах уведомления с макетным объектом. Фактический патч - это изменить объект, на который указывает канал name, используемый в уведомлении. Название Channel в тестовом модуле уже определено, поэтому оно не изменяется. Это на самом деле лучше объясняется здесь: http://www.voidspace.org.uk/python/mock/patch.html#id1
Чтобы получить доступ к исправленной версии вашего объекта, вы можете напрямую обратиться к модулю:
import unittest
from mock import patch
from notification.models import Channel, addChannelWithName
from notification import models
class TestChannel1(unittest.TestCase):
@patch("notification.models.Channel")
def testAddChannelWithNamePutsChannel(self, *args):
addChannelWithName("channel1")
models.Channel.put.assert_called_with("channel1")
Или используйте исправленную версию, переданную в качестве дополнительного аргумента в декорированную функцию:
class TestChannel2(unittest.TestCase):
@patch("notification.models.Channel")
def testAddChannelWithNamePutsChannel(self, mock_channel):
addChannelWithName("channel1")
mock_channel.put.assert_called_with("channel1")
Если вы просто хотите быстро исправить один метод для объекта, обычно проще использовать декоратор patch.object
:
class TestChannel3(unittest.TestCase):
@patch.object(Channel, 'put')
def testAddChannelWithNamePutsChannel(self, *arg):
addChannelWithName("channel1")
Channel.put.assert_called_with("channel1")