diff --git a/CHANGELOG b/CHANGELOG index 39c2da126..4daca0687 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,9 @@ NEXT (2.6) ----------------------------------- +- fix issue473: work around mock putting an unbound method into a class + dict when double-patching. + - fix issue498: if a fixture finalizer fails, make sure that the fixture is still invalidated. diff --git a/_pytest/python.py b/_pytest/python.py index 25a5f5c67..7c43c8019 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -222,6 +222,8 @@ def pytest_pycollect_makeitem(__multicall__, collector, name, obj): return Class(name, parent=collector) elif collector.funcnamefilter(name) and hasattr(obj, "__call__") and \ getfixturemarker(obj) is None: + # mock seems to store unbound methods (issue473), let's normalize it + obj = getattr(obj, "__func__", obj) if not isfunction(obj): collector.warn(code="C2", message= "cannot collect %r because it is not a function." diff --git a/testing/python/integration.py b/testing/python/integration.py index b51fc7766..8798f643b 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -164,6 +164,21 @@ class TestMockDecoration: names = [x.nodeid.split("::")[-1] for x in calls] assert names == ["test_one", "test_two", "test_three"] + def test_mock_double_patch_issue473(self, testdir): + testdir.makepyfile(""" + from mock import patch + from pytest import mark + + @patch('os.getcwd') + @patch('os.path') + @mark.slow + class TestSimple: + def test_simple_thing(self, mock_path, mock_getcwd): + pass + """) + res = testdir.inline_run() + res.assertoutcome(passed=1) + class TestReRunTests: def test_rerun(self, testdir):