TypeError: Need a valid target to patch. You supplied: 'MyClass'
import unittest from mock import Mock,MagicMock,patch from notification.models import Channel,addChannelWithName,deleteChannelWithName,listAllChannelNames class TestChannel(unittest.TestCase): @patch("Channel") def testAddChannelWithNamePutsChannel(self,*args): addChannelWithName("channel1") Channel.put.assert_called_with()
import unittest from mock import Mock,listAllChannelNames class TestChannel(unittest.TestCase): @patch("notification.models.Channel") def testAddChannelWithNamePutsChannel(self,*args): addChannelWithName("channel1") Channel.put.assert_called_with()
这是为什么?为什么我可以在其他地方将Channel称为“Channel”,但是对于补丁,我需要模块前缀才能得到错误?此外,我有一种感觉,给予完整的模块前缀不工作,因为当我调用Channel.put.assert_called_with()我得到的错误,assert_called_with不是Channel.put的属性.有人可以解释发生了什么吗?非常感谢
解决方法
target should be a string in the form ‘package.module.ClassName’. The target is imported and the specified object replaced with the new object,so the target must be importable from the environment you are calling patch from. The target is imported when the decorated function is executed,not at decoration time.
“Channel”只是一个字符串,而patch没有足够的信息来找到正确的类.这与您在其他地方使用的名称Channel不同,后者是在模块顶部导入的.
第二个测试失败,因为通道在测试模块中导入,然后修补程序使用mock对象替换notification.models中的Channel.什么补丁实际上是改变对象的名称通道在notification.models内使用指向.测试模块中的通道名称已经定义,因此不受影响.这实际上在这里更好地解释: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")