Skip to content
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

Mypy throws errors when MagicMock-ing a method #6713

Closed
MatanRubin opened this issue Apr 23, 2019 · 5 comments
Closed

Mypy throws errors when MagicMock-ing a method #6713

MatanRubin opened this issue Apr 23, 2019 · 5 comments
Labels
false-positive mypy gave an error on correct code feature priority-2-low

Comments

@MatanRubin
Copy link

Using Python 3.7 and MyPy 0.700.

When MagicMocking a method and then using MagicMock methods, mypy complains that the mocked method does not have the attribute "assert_called" and other MagicMock methods.
I'm not sure if it's at all possible for mypy to understand a method was monkey-patched like this, but it makes checking tests involving Mocks with mypy is not practical. Ideally, this code should not throw any errors.

For example:

from unittest.mock import MagicMock


class Foo:
    def bar(self) -> None:
        pass


foo = Foo()
foo.bar = MagicMock()
foo.bar()
foo.bar.assert_called()

When running Mypy, you get:

test.py:10: error: Cannot assign to a method
test.py:12: error: "Callable[[], None]" has no attribute "assert_called"

The first error is already discussed in #2427.
I couldn't find an issue discussing the second error.

@ilevkivskyi
Copy link
Member

I could see how this can be problematic, but this is hard to support. First, we would need to add at least some basic generic support for monkey-patching.

@ilevkivskyi ilevkivskyi added feature priority-2-low false-positive mypy gave an error on correct code labels Apr 25, 2019
@graingert
Copy link
Contributor

The context manager patch interface should work here:

from unittest.mock import MagicMock


class Foo:
    def bar(self) -> None:
        pass


foo = Foo()
with mock.patch.object(foo, "bar") as bar:
    foo.bar()
bar.assert_called()

@david-shiko
Copy link

The context manager patch interface should work here:

from unittest.mock import MagicMock


class Foo:
    def bar(self) -> None:
        pass


foo = Foo()
with mock.patch.object(foo, "bar") as bar:
    foo.bar()
bar.assert_called()

What if the mocked object is pytest fixture, how to specify the return type?

@vors
Copy link

vors commented Jan 30, 2023

A more complex cases are still not well-covered. For example when the mock setup is split into separate methods and so on.

pytorchmergebot pushed a commit to pytorch/pytorch that referenced this issue Jul 29, 2023
…05251)

Currently all information about the dependencies of ghstack PRs (e.g. #105010) is stripped away:
https://github.com/pytorch/pytorch/blob/c984885809194e0a807b3f5543450fae4dfa841a/.github/scripts/trymerge.py#L1077-L1078

This PR adds this information back in a more compact form. All dependencies (PR numbers) of each PR in ghstack are recorded.

The resulting commit message will look like this (the last line is new):

> Mock title (#123)
>
> Mock body text
> Pull Request resolved: #123
> Approved by: https://github.com/Approver1, https://github.com/Approver2
> ghstack dependencies: #1, #2

---

### Testing

Unit tests.

---

### Note Re: `# type: ignore[assignment]` in unit tests.

I did my due diligence to find alternatives. Unfortunately mypy [doesn't](python/mypy#6713) support this [way of patching methods](https://docs.python.org/3/library/unittest.mock-examples.html#mock-patching-methods), and the alternatives are either extremely verbose or don't work for this case. I decided it's not worth the effort (since the problem is limited only to the unit test).
Pull Request resolved: #105251
Approved by: https://github.com/huydhn
@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Aug 22, 2023

With modern mypy and typeshed, you only get the "Cannot assign to a method".

If the context manager solution graingert mentions doesn't work for you, and you'd like to avoid this error, use --disable-error-code=method-assign (this can be enabled on a per-file basis). See also #2427 (comment)

Feel free to open new issues for other examples involving mock, although mock is very dynamic and is unlikely to ever be fully understandable by static type checkers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
false-positive mypy gave an error on correct code feature priority-2-low
Projects
None yet
Development

No branches or pull requests

6 participants