python – 补丁 – 为什么相对补丁目标名称不会工作?

前端之家收集整理的这篇文章主要介绍了python – 补丁 – 为什么相对补丁目标名称不会工作?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我从一个模块导入了一个类,但是当我尝试修补类名称而不将它作为前缀时,我得到一个类型错误
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的属性.有人可以解释发生了什么吗?非常感谢

解决方法

补丁装饰器要求目标是一个完整的虚线路径,如 documentation所述:

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")

猜你在找的Python相关文章