如何使用模拟库修补Python类

如何使用模拟库修补Python类,python,unit-testing,mocking,scrapy,python-mock,Python,Unit Testing,Mocking,Scrapy,Python Mock,我很难为我的测试修补一个类。我正在尝试修补属于Scrapy-a类的东西 下面是一些代码: from scrapy.selector import HtmlXPathSelector from mock import MagicMock, patch with patch('scrapy.selector.HtmlXPathSelector') as MockHtml: instance = MockHtml.return_value instance.method.return

我很难为我的测试修补一个类。我正在尝试修补属于Scrapy-a类的东西

下面是一些代码:

from scrapy.selector import HtmlXPathSelector
from mock import MagicMock, patch

with patch('scrapy.selector.HtmlXPathSelector') as MockHtml:
    instance = MockHtml.return_value
    instance.method.return_value = 'foo'
    example = HtmlXPathSelector()
    print type(example)
    assert example is instance
    assert example.method == 'foo'
结果是:

<class 'scrapy.selector.lxmlsel.HtmlXPathSelector'>
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
AssertionError
>>>

回溯(最近一次呼叫最后一次):
文件“”,第6行,在
断言错误
>>>

此示例与模拟库教程中的示例几乎相同。知道它为什么不工作吗?

您不应该修补当前测试代码中已导入的类。相反,您需要在相应的模块(您想要测试)中修补该类。因此,如果在
mymodule
中导入了
HtmlXPathSelector
,您将作为以下内容进行修补:

with patch('mymodule.HtmlXPathSelector') as MockClass:
    ...
有关更多详细信息,请参阅

编辑如果确实需要,可以使用以下内容修补当前模块中的类:

with patch('__main__.Class') as MockClass:

您的代码示例有两个问题。首先,您已经从scrapy模块中导入了HtmlXPathSelector,然后在事实发生后更改该名称。改为导入选择器,并使用其中的名称:

from scrapy import selector
from mock import MagicMock, patch

with patch('scrapy.selector.HtmlXPathSelector') as MockHtml:
    instance = MockHtml.return_value
    instance.method.return_value = 'foo'
    example = selector.HtmlXPathSelector()
    print type(example)
    assert example is instance
    assert example.method() == 'foo'

另一个问题是,您的最后一行正在检查
方法
,当它需要调用方法作为
方法()

这太好了,谢谢!唯一的问题是,我在问题中给出的例子稍微简化了。。。事实上,在我正在测试的模块中,
mypackage.foo_模块
htmlxpath选择器
是这样导入的:
从scrapy.selector导入htmlxpath选择器
,然后我正在测试的函数有一个实例化,比如
hxs=htmlxpath选择器(XX)
。我是否必须更改我正在测试的类中的代码才能使其正常工作?或者更改产品代码以按照此示例的方式导入,或者使用
patch('mypackage.foo_module.HtmlXPathSelector')
。第二种方式可能更好,因为这是一种更本地化的更改。我现在明白了,内德,谢谢。我刚才无意中听到了你的谈话。然后你回答了我的测试问题。真奇怪。:-)啊!这就是我想要的。。。我现在明白了,这个方法回答了我在Ned的回答中的评论。谢谢此时修补的链接返回503。@Drachenfels谢谢,将链接更改为指向readthedocs,应该更稳定。