title: pytest-monkeypatch a decorator (not using mock / patch)
body: <p>I am writing some tests using pytest with the monkeypatch fixture. Following the rules I am importing the classes and methods to mock out from the module they are being used in and not from the source.</p>
  
  <p>The application I am writing tests for is a Google App Engine application which uses the Standard environment. As such I have to use python 2.7, the actual version I am using is 2.7.15 - pytest version is 3.5.0</p>
  
  <p>Everything has been working well so far but I have hit a problem when trying to mock out a decorator function.</p>
  
  <p>Starting from the top. In a py file called decorators.py contains all the auth decorators including the decorator I want to mock out. The decorator in question is a module function, not part of a class.</p>
  
  <pre><code>def user_login_required(handler):
      def is_authenticated(self, *args, **kwargs):
          u = self.auth.get_user_by_session()
          if u.access == '' or u.access is None:
              # return the response
              self.redirect('/admin', permanent=True)
          else:
              return handler(self, *args, **kwargs)
      return is_authenticated
  </code></pre>
  
  <p>The decorator is applied to the web request function. A basic example in a file called UserDetails.py in a folder called handlers (handlers.UserDetails)</p>
  
  <pre><code>from decorators import user_login_required
  
  class UserDetailsHandler(BaseHandler):
      @user_login_required
      def get(self):
          # Do web stuff, return html, etc
  </code></pre>
  
  <p>In a test module I am setting up the test like this:</p>
  
  <pre><code>from handlers.UserDetails import user_login_required
  
  @pytest.mark.parametrize('params', get_params, ids=get_ids)
  def test_post(self, params, monkeypatch):
  
      monkeypatch.setattr(user_login_required, mock_user_login_required_func)
  </code></pre>
  
  <p>The problem with this is that monkeypatch does not allow me to put a single function in as the target. It wants the target to be a Class, followed by the method name to be replaced then the mock method....</p>
  
  <pre><code>monkeypatch.setattr(WouldBeClass, "user_login_required", mock_user_login_required_func)
  </code></pre>
  
  <p>I have tried to adjust the code to see if I can get round it by changing how the decorator is imported and used like this:</p>
  
  <pre><code>import decorators
  
  class UserDetailsHandler(BaseHandler):
      @decorators.user_login_required
      def get(self):
          # Do web stuff, return html, etc
  </code></pre>
  
  <p>Then in the test I try to patch the function name like so.....</p>
  
  <pre><code>from handlers.UserDetails import decorators
  
  @pytest.mark.parametrize('params', get_params, ids=get_ids)
  def test_post(self, params, monkeypatch):
  
      monkeypatch.setattr(decorators, "user_login_required" , mock_user_login_required_func)
  </code></pre>
  
  <p>Although this code does not throw any errors, when I step through the test the code never enters the mock_user_login_required_func. It always goes into the live decorator.</p>
  
  <p>What am I doing wrong? This this a problem with trying to monkeypatch decorators in general or can lone functions in modules not be patched?</p>