gpt4 book ai didi

python - 补丁 - 为什么相对补丁目标名称不起作用?

转载 作者:IT老高 更新时间:2023-10-28 21:00:27 28 4
gpt4 key购买 nike

我已经从一个模块中导入了一个类,但是当我尝试在没有模块作为前缀的情况下修补类名时,我得到一个类型错误:

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, MagicMock, patch
from notification.models import Channel, addChannelWithName, deleteChannelWithName, 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_call_with() 时,我收到 assert_call_with 不是 Channel.put 的属性的错误。有人可以解释发生了什么吗?非常感谢!

最佳答案

patch 装饰器要求目标是完整的虚线路径,如 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 不同,后者是在模块顶部导入的。

第二个测试失败,因为 Channel 被导入到测试模块中然后补丁用模拟对象替换 notification.models 中的 Channel。 patch 实际所做的是更改在 notification.models 中使用的 name Channel 指向的对象。测试模块中的名称 Channel 已经定义好了,所以不受影响。这实际上在这里得到了更好的解释:https://docs.python.org/3/library/unittest.mock.html#where-to-patch

要访问对象的修补版本,您可以直接访问模块:

import unittest 
from unittest.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 - 补丁 - 为什么相对补丁目标名称不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16060724/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com