Skip to content

unitest.mock: Using autospec=True conflicts with 'wraps' #75988

Closed

Description

@JohnVillalovos
BPO 31807
Nosy @rbtcollins, @ezio-melotti, @voidspace, @Lukas0907, @tirkarthi
Files
  • 0001-bpo-31807-unittest.mock-Fix-common-use-of-autospec-T.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2017-10-18.00:48:15.176>
    labels = ['3.7', 'type-bug', 'library']
    title = "unitest.mock: Using autospec=True conflicts with 'wraps'"
    updated_at = <Date 2019-12-02.08:29:10.129>
    user = 'https://bugs.python.org/JohnVillalovos'

    bugs.python.org fields:

    activity = <Date 2019-12-02.08:29:10.129>
    actor = 'xtreak'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2017-10-18.00:48:15.176>
    creator = 'John Villalovos'
    dependencies = []
    files = ['47267']
    hgrepos = []
    issue_num = 31807
    keywords = ['patch']
    message_count = 3.0
    messages = ['304549', '306273', '352287']
    nosy_count = 6.0
    nosy_names = ['rbcollins', 'ezio.melotti', 'michael.foord', 'John Villalovos', 'Lukas Anzinger', 'xtreak']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue31807'
    versions = ['Python 3.6', 'Python 3.7']

    Linked PRs

    Activity

    1. JohnVillalovos commented on Oct 18, 2017

      JohnVillalovosmannequin
      MannequinAuthor

      If have autospec=True, then no ValueError is raised. If autospec=False or not defined, then the ValueError is raised.

      import sys
      from unittest import mock
      
      def wrapped_func(value):
          raise ValueError(value)

      @mock.patch('__main__.wrapped_func', autospec=True, wraps=wrapped_func)
      def main(mock_wrap):

          wrapped_func("testing")
      
      if '__main__' == __name__:
          sys.exit(main())
    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-bugAn unexpected behavior, bug, or error
      on Oct 18, 2017
    3. changed the title [-]Using autospec=True conflicts with 'wraps'[/-] [+]unitest.mock: Using autospec=True conflicts with 'wraps'[/+] on Oct 18, 2017
    4. Lukas0907 commented on Nov 15, 2017

      Lukas0907mannequin
      Mannequin

      I can reproduce the problem and have analyzed it a bit. My use case is a bit different, I want to use autospec=True and wraps= so that I can mock unbound methods but return the result from the original method (see also https://docs.python.org/3/library/unittest.mock-examples.html#mocking-unbound-methods).

      The problem in the mock code is that mock.return_value actually calls __get_return_value() which replaces the actual return value mock.DEFAULT (which is stored in self._mock_return_value) with a new child mock. When the mock is then called and _mock_call() is executed, the wrapped function is not executed because self._mock_return_value is not mock.DEFAULT anymore:

          if (self._mock_wraps is not None and
               self._mock_return_value is DEFAULT):
              return self._mock_wraps(*args, **kwargs)
          if ret_val is DEFAULT:
              ret_val = self.return_value
          return ret_val

      Since self._mock_return_value is not DEFAULT anymore it doesn't matter if the mock wraps something and it will instead just return a new mock.

      I think that the side effect of the assignment to self.return_value in _setup_func() is not intentional, i.e. the child mock should actually be created only if there is an outside access to return_value, but not when it is just wrapped in a function. The assignment can be made side effect free by assigning the internal attribute _mock_return_value (see attached patch). This solves the problem for me.

      I've attached a patch that fixes the problem and doesn't seem to introduce a regression (all unittest.mock tests pass).

      If somebody is interested in getting this merged, I'm happy to provide a regression test and everything else that is needed to get this merged.

      Cheers,

      Lukas

    5. Lukas0907 commented on Sep 13, 2019

      Lukas0907mannequin
      Mannequin

      Hi,

      I just wanted to ask what the status for this bug is.

      I'm still interested in getting this merged and would be happy to help.

      Lukas

    6. transferred this issue fromon Apr 10, 2022
    7. e-gebes commented on Jan 10, 2023

      @e-gebes

      I ran into the same issue with methods like @Lukas0907 described it, on Python 3.10.

    8. added a commit that references this issue on Mar 8, 2024
    9. added 2 commits that reference this issue on Mar 21, 2024
    10. added 2 commits that reference this issue on Mar 22, 2024
    11. added a commit that references this issue on Mar 25, 2024
    12. added a commit that references this issue on Apr 17, 2024
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.7 (EOL)end of lifestdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

      Projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions