Skip to content

Inheriting from instantiated generic class causes mocking to fail #250

Closed

Description

@jhance

My reproduction (python 2)

import mock

from typing import Generic, TypeVar

T = TypeVar('T')

class Bar(Generic[T]):
    def __init__(self):
        pass

    def do_bar(self):
        print("bar")

class Foo(Bar[int]):
    def do_foo(self):
        self.do_bar()

@mock.patch.object(Bar, 'do_bar')
def mocked(mock_do_bar):
    mock_do_bar.return_value = None
    foo = Foo()
    foo.do_foo()

mocked()

will unexpectedly print bar.

The inheritance here is crucial.

Activity

  1. gvanrossum commented on Jul 20, 2016

    @gvanrossum
    Member

    (PS try to trim trailing whitespace when copy/pasting text into github. It causes spurious horizontal scroll bars to appear and weird line breaks. I cleaned it up for you this time.)

  2. jhance commented on Jul 20, 2016

    @jhance
    Author

    Oh, I did not realize I somehow accrued trailing whitespace. Must have been because I pastebin'd it to Jukka then copied from there. Sorry about that :(

  3. gvanrossum commented on Jul 20, 2016

    @gvanrossum
    Member

    Anyway, I do think this is a bug, but I don't know how to fix it. Looking at the MRO for Foo, we have:

    [__main__.Foo,
     __main__.Bar<~T>[int],
     __main__.Bar<~T>,
     typing.Generic<~T>,
     typing.Generic,
     <type 'object'>]

    I think the double occurrence of Bar may be the problem -- you're patching the original, but the MRO search finds the unpatched copy in Bar[int].

    I think here's a workaround:

    ...
    BarInt = Bar[int]
    
    class Foo(BarInt):
        def do_foo(self):
            self.do_bar()
    
    @mock.patch.object(BarInt, 'do_bar')
    def mocked(mock_do_bar):
    ...
  4. jhance commented on Jul 20, 2016

    @jhance
    Author

    I see.

    Well, a workaround is good enough for now. Thanks! (It has the somewhat unfortunate property that you have to mock all the instantiations being used - but in my case that is only 2 of them, which isn't so bad).

    Edit: Confirmation that the workaround indeed works around.

  5. modified the milestone: 3.5.3 on Aug 26, 2016
  6. added a commit that references this issue on Oct 9, 2016
  7. gvanrossum commented on Oct 11, 2016

    @gvanrossum
    Member

    Sorry, this wasn't fixed by #289.

  8. added a commit that references this issue on Oct 21, 2016
  9. jhance commented on Oct 28, 2016

    @jhance
    Author

    Thanks :D

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions