Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JohnVillalovos mannequin opened this issue Oct 18, 2017 · 4 comments
Closed

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

JohnVillalovos mannequin opened this issue Oct 18, 2017 · 4 comments
Labels
3.7 (EOL) end of life stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@JohnVillalovos
Copy link
Mannequin

JohnVillalovos mannequin commented Oct 18, 2017

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

    @JohnVillalovos
    Copy link
    Mannequin Author

    JohnVillalovos mannequin commented Oct 18, 2017

    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())

    @JohnVillalovos JohnVillalovos mannequin added stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error labels Oct 18, 2017
    @JohnVillalovos JohnVillalovos mannequin changed the title Using autospec=True conflicts with 'wraps' unitest.mock: Using autospec=True conflicts with 'wraps' Oct 18, 2017
    @Lukas0907
    Copy link
    Mannequin

    Lukas0907 mannequin commented Nov 15, 2017

    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

    @Lukas0907 Lukas0907 mannequin added the 3.7 (EOL) end of life label Nov 15, 2017
    @Lukas0907
    Copy link
    Mannequin

    Lukas0907 mannequin commented Sep 13, 2019

    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

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @e-gebes
    Copy link

    e-gebes commented Jan 10, 2023

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

    cjw296 pushed a commit that referenced this issue Mar 8, 2024
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    @cjw296 cjw296 closed this as completed Mar 17, 2024
    infohash added a commit to infohash/cpython that referenced this issue Mar 21, 2024
    …hon#115223)
    
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    
    (cherry picked from commit 735fc2c)
    infohash added a commit to infohash/cpython that referenced this issue Mar 21, 2024
    …hon#115223)
    
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    
    (cherry picked from commit 735fc2c)
    cjw296 pushed a commit that referenced this issue Mar 22, 2024
    …-115223) (#117119)
    
    gh-75988: Fix issues with autospec ignoring wrapped object (#115223)
    
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    
    (cherry picked from commit 735fc2c)
    cjw296 pushed a commit that referenced this issue Mar 22, 2024
    …-115223) (#117124)
    
    gh-75988: Fix issues with autospec ignoring wrapped object (#115223)
    
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    
    (cherry picked from commit 735fc2c)
    adorilson pushed a commit to adorilson/cpython that referenced this issue Mar 25, 2024
    …hon#115223)
    
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    diegorusso pushed a commit to diegorusso/cpython that referenced this issue Apr 17, 2024
    …hon#115223)
    
    * set default return value of functional types as _mock_return_value
    
    * added test of wrapping child attributes
    
    * added backward compatibility with explicit return
    
    * added docs on the order of precedence
    
    * added test to check default return_value
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    Status: Done
    Development

    No branches or pull requests

    2 participants
    pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy