Question

I'm having trouble patching a class for my testing. I'm trying to patch something that belongs to Scrapy - a HtmlXpathSelector class.

Here is some code:

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'

The result is:

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

This example is nigh on the same as the one in the Mock library tutorial. Any idea why it's not working?

Was it helpful?

Solution

You should not patch a class already imported in the current test code. Instead you need to patch the class in the corresponding module (you want to test). So if HtmlXPathSelector is imported in mymodule, you will patch as:

with patch('mymodule.HtmlXPathSelector') as MockClass:
    ...

See where to patch for further details.

Edit If you really need this, you can patch a class in the current module with:

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

OTHER TIPS

There are two problems with your code sample. The first is that you've imported HtmlXPathSelector from the scrapy module, then you change that name after the fact. Import selector instead, and use the name from there:

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'

The other problem is that your last line was checking method, when it needs to invoke the method as method().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top