Merge pull request #5631 from RonnyPfannschmidt/fix-5606

use identity checks for the mock sentinels
This commit is contained in:
Bruno Oliveira 2019-07-23 08:48:58 -03:00 committed by GitHub
commit ec4ca59bf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 7 deletions

View File

@ -0,0 +1,2 @@
Fixed internal error when test functions were patched with objects that cannot be compared
for truth values against others, like ``numpy`` arrays.

View File

@ -64,13 +64,18 @@ def num_mock_patch_args(function):
patchings = getattr(function, "patchings", None)
if not patchings:
return 0
mock_modules = [sys.modules.get("mock"), sys.modules.get("unittest.mock")]
if any(mock_modules):
sentinels = [m.DEFAULT for m in mock_modules if m is not None]
return len(
[p for p in patchings if not p.attribute_name and p.new in sentinels]
)
return len(patchings)
mock_sentinel = getattr(sys.modules.get("mock"), "DEFAULT", object())
ut_mock_sentinel = getattr(sys.modules.get("unittest.mock"), "DEFAULT", object())
return len(
[
p
for p in patchings
if not p.attribute_name
and (p.new is mock_sentinel or p.new is ut_mock_sentinel)
]
)
def getfuncargnames(function, is_method=False, cls=None):

View File

@ -178,6 +178,34 @@ class TestMockDecoration:
reprec = testdir.inline_run()
reprec.assertoutcome(passed=2)
def test_mock_sentinel_check_against_numpy_like(self, testdir):
"""Ensure our function that detects mock arguments compares against sentinels using
identity to circumvent objects which can't be compared with equality against others
in a truth context, like with numpy arrays (#5606).
"""
testdir.makepyfile(
dummy="""
class NumpyLike:
def __init__(self, value):
self.value = value
def __eq__(self, other):
raise ValueError("like numpy, cannot compare against others for truth")
FOO = NumpyLike(10)
"""
)
testdir.makepyfile(
"""
from unittest.mock import patch
import dummy
class Test(object):
@patch("dummy.FOO", new=dummy.NumpyLike(50))
def test_hello(self):
assert dummy.FOO.value == 50
"""
)
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
def test_mock(self, testdir):
pytest.importorskip("mock", "1.0.1")
testdir.makepyfile(