title: Getting monkeypatching in pytest to work
body: <p>I'm trying to develop a test using pytest for a class method that randomly selects a string from a list of strings. </p>
  
  <p>It looks essentially like the givemeanumber method below:</p>
  
  <pre><code>import os.path
  from random import choice
  
  class Bob(object):
    def getssh():
      return os.path.join(os.path.expanduser("~admin"), '.ssh')
  
    def givemeanumber():
      nos = [1, 2, 3, 4]
      chosen = choice(nos)
      return chosen
  </code></pre>
  
  <p>the first method, getssh, in the class Bob is just the example from the <a href="https://docs.pytest.org/en/latest/monkeypatch.html" rel="nofollow noreferrer">pytest docs</a></p>
  
  <p>My production code fetches a list of strings from a DB and then randomly selects one. So I'd like my test to fetch the strings and then instead of randomly selecting, it selects the first string. That way I can test against a known string.  </p>
  
  <p>From my reading I reckon I need to use monkeypatching to fake the randomisation. </p>
  
  <p>Here's what I've got so far</p>
  
  <pre><code>import os.path
  from random import choice
  from _pytest.monkeypatch import MonkeyPatch
  from bob import Bob
  
  class Testbob(object):
      monkeypatch = MonkeyPatch()
  
      def test_getssh(self):
          def mockreturn(path):
              return '/abc'
          Testbob.monkeypatch.setattr(os.path, 'expanduser', mockreturn)
          x = Bob.getssh()
          assert x == '/abc/.ssh'
  
      def test_givemeanumber(self):
          Testbob.monkeypatch.setattr('random.choice',  lambda x: x[0])
          z = Bob.givemeanumber()
          assert z == 1
  </code></pre>
  
  <p>The first test method is again the example from the pytest docs (adapted slightly as I'm using it in a test class). This works fine. </p>
  
  <p>Following the example from the docs I would expect to use 
  <code>Testbob.monkeypatch.setattr(random, 'choice',  lambda x: x[0])</code>
  but this yields 
  <code>NameError: name 'random' is not defined</code></p>
  
  <p>if I change it to
  <code>Testbob.monkeypatch.setattr('random.choice',  lambda x: x[0])</code></p>
  
  <p>it gets further but no swapping out occurs:
  <code>AssertionError: assert 2 == 1</code></p>
  
  <p>Is monkeypatching the right tool for the job? 
  If it is where am I going wrong?</p>