How to mock random.choice in python?
<p>I want <code>choice</code> to return the same value <code>1000</code> every time in my unittest. The following code doesn't work.</p>

<pre><code>import unittest
from random import choice

from mock import mock

def a():
    return choice([1, 2, 3])

class mockobj(object):
    @classmethod
    def choice(cls, li):
        return 1000

class testMock(unittest.TestCase):

    def test1(self):
        with mock.patch('random.choice', mockobj.choice):
            self.assertEqual(a(), 1000)
</code></pre>

<p>The error message is as follows:</p>

<pre><code>Failure
Traceback (most recent call last):
  File "test.py", line 15, in test1
    self.assertEqual(a(), 1000)
AssertionError: 3 != 1000
</code></pre>

<p>How should I modify it to make it work? I'm using python2.7</p>

<p>The problem here is that <code>a()</code> is using an <em>unpatched</em> version of <code>random.choice</code>.</p>

<p>Compare functions <code>a</code> and <code>b</code>:</p>

<pre><code>import random
from random import choice

def a():
    return choice([1, 2, 3])

def b():
    return random.choice([1, 2, 3])

def choice1000(values):
    return 1000

import unittest.mock as mock

with mock.patch('random.choice', choice1000):
    print('a', a())
    print('b', b())
</code></pre>

<p>It prints e.g.:</p>

<pre><code>a 3
b 1000
</code></pre>

<h1>Why?</h1>

<p>This line is the problem:</p>

<pre><code>from random import choice
</code></pre>

<p>It imported <code>random</code> and than stored <code>random.choice</code> into a new variable named <code>choice</code>.</p>

<p>Later, <code>mock.patch</code> patched the original <code>random.choice</code>, but not the local <code>choice</code>.</p>

<p>Can I patch the local one? Yes:</p>

<pre><code>with mock.patch('__main__.choice', choice1000):
    print('a', a())
    print('b', b())
</code></pre>

<p>Now it prints e.g.</p>

<pre><code>a 1000
b 1
</code></pre>

<p>(I used <code>'__main__'</code> because I put this code into the <a href="https://docs.python.org/3/library/__main__.html" rel="nofollow">top-level file</a> - it may be something else in your case)</p>

<h2>So what to do?</h2>

<p>Either patch everything, or take a different approach. For example, patch <code>a()</code> instead of <code>choice()</code>.</p>

<h1>Alternative Solution</h1>

<p>In this case, where you want to test behaviour of <code>random</code> functions, it may be better to use a <a href="https://docs.python.org/2/library/random.html#random.seed" rel="nofollow">seed</a></p>

<pre><code>def a():
    return random.choice([1, 2, 3, 1000])

def test1(self):
    random.seed(0)
    self.assertEqual(a(), 1000)
</code></pre>

<p>You can't know beforehand what random values will be generated for a certain seed, but you can be sure that they will always be the same. Which is exactly what you need in tests.</p>

<p>In the last example above, I tested <code>a()</code> after <code>random.seed(0)</code> once and it returned 1000, so I can be sure it will do so every time:</p>

<pre><code>&gt;&gt;&gt; import random
&gt;&gt;&gt; random.seed(0)
&gt;&gt;&gt; print (random.choice([1, 2, 3, 1000]))
1000
&gt;&gt;&gt; random.seed(0)
&gt;&gt;&gt; print (random.choice([1, 2, 3, 1000]))
1000
&gt;&gt;&gt; random.seed(0)
&gt;&gt;&gt; print (random.choice([1, 2, 3, 1000]))
1000
&gt;&gt;&gt; random.seed(0)
&gt;&gt;&gt; print (random.choice([1, 2, 3, 1000]))
1000
</code></pre>

python unit-testing mocking