Can a MagicMock object be iterated over?
<p>What I would like to do is this...</p>

<pre><code>x = MagicMock()
x.iter_values = [1, 2, 3]

for i in x:
    i.method()
</code></pre>

<p>I am trying to write a unit test for this function but I am unsure about how to go about mocking all of the methods called without calling some external resource...</p>

<pre><code>def wiktionary_lookup(self):
    """Looks up the word in wiktionary with urllib2, only to be used for inputting data"""
    wiktionary_page = urllib2.urlopen(
        "http://%s.wiktionary.org/wiki/%s" % (self.language.wiktionary_prefix, self.name))
    wiktionary_page = fromstring(wiktionary_page.read())
    definitions = wiktionary_page.xpath("//h3/following-sibling::ol/li")
    print definitions.text_content()
    defs_list = []
    for i in definitions:
        print i
        i = i.text_content()
        i = i.split('\n')
        for j in i:
            # Takes out an annoying "[quotations]" in the end of the string, sometimes.
            j = re.sub(ur'\u2003\[quotations \u25bc\]', '', j)
            if len(j) &gt; 0:
                defs_list.append(j)
    return defs_list
</code></pre>

<p>EDIT:</p>

<p>I may be misusing mocks, I am not sure. I am trying to unit-test this <code>wiktionary_lookup</code> method without calling external services...so I mock urlopen..I mock fromstring.xpath() but as far as I can see I need to also iterate through the return value of <code>xpath()</code> and call a method "<code>text_contents()</code>" so that is what I am trying to do here.</p>

<p>If I have totally misunderstood how to unittest this method then please tell me where I have gone wrong... </p>

<p>EDIT (adding current unittest code)</p>

<pre><code>@patch("lang_api.models.urllib2.urlopen")
@patch("lang_api.models.fromstring")
def test_wiktionary_lookup_2(self, fromstring, urlopen):
    """Looking up a real word in wiktionary, should return a list"""
    fromstring().xpath.return_value = MagicMock(
        content=["test", "test"], return_value='test\ntest2')
    # A real word should give an output of definitions
    output = self.things.model['word'].wiktionary_lookup()
    self.assertEqual(len(output), 2)
</code></pre>

<p>What you actually want to do is not return a <code>Mock</code> with a <code>return_value=[]</code>. You actually want to return a <code>list</code> of <code>Mock</code> objects. Here is a snippet of your test code with the correct components and a small example to show how to test one of the iterations in your loop: </p>

<pre><code>@patch('d.fromstring')
@patch('d.urlopen')
def test_wiktionary(self, urlopen_mock, fromstring_mock):
    urlopen_mock.return_value = Mock()
    urlopen_mock.return_value.read.return_value = "some_string_of_stuff"

    mocked_xpath_results = [Mock()]
    fromstring_mock.return_value.xpath.return_value = mocked_xpath_results

    mocked_xpath_results[0].text_content.return_value = "some string"
</code></pre>

<p>So, to dissect the above code to explain what was done to correct your problem: </p>

<p>The first thing to help us with testing the code in the for loop is to create a list of mock objects per: </p>

<pre><code>mocked_xpath_results = [Mock()]
</code></pre>

<p>Then, as you can see from </p>

<pre><code>fromstring_mock.return_value.xpath.return_value = mocked_xpath_results
</code></pre>

<p>We are setting the <code>return_value</code> of the <code>xpath</code> call to our list of mocks per <code>mocked_xpath_results</code>. </p>

<p>As an example of how to do things inside your list, I added how to mock within the loop, which is shown with:</p>

<pre><code>mocked_xpath_results[0].text_content.return_value = "some string"
</code></pre>

<p>In unittests (this might be a matter of opinion) I like to be explicit, so I'm accessing the list item explicitly and determining what should happen. </p>

<p>Hope this helps. </p>

python django unit-testing mocking