From fa4c4bb5a34d73acf1fe8860c6967a35fce5135d Mon Sep 17 00:00:00 2001 From: Matus Valo Date: Wed, 15 Sep 2021 12:38:46 +0200 Subject: Remove dependency to case --- requirements/test.txt | 1 - t/mocks.py | 24 +++++++++++++++++++++ t/unit/conftest.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++ t/unit/test_channel.py | 2 +- t/unit/test_connection.py | 3 ++- 5 files changed, 81 insertions(+), 3 deletions(-) create mode 100644 t/mocks.py create mode 100644 t/unit/conftest.py diff --git a/requirements/test.txt b/requirements/test.txt index 57c3734..242016f 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,4 +1,3 @@ -case>=1.3.1 pytest>=3.0,<=5.3.5 pytest-sugar>=0.9.1 pytest-rerunfailures>=6.0 diff --git a/t/mocks.py b/t/mocks.py new file mode 100644 index 0000000..f91ae9b --- /dev/null +++ b/t/mocks.py @@ -0,0 +1,24 @@ +from unittest.mock import Mock + +class _ContextMock(Mock): + """Dummy class implementing __enter__ and __exit__ + as the :keyword:`with` statement requires these to be implemented + in the class, not just the instance.""" + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + pass + + +def ContextMock(*args, **kwargs): + """Mock that mocks :keyword:`with` statement contexts.""" + obj = _ContextMock(*args, **kwargs) + obj.attach_mock(_ContextMock(), '__enter__') + obj.attach_mock(_ContextMock(), '__exit__') + obj.__enter__.return_value = obj + # if __exit__ return a value the exception is ignored, + # so it must return None here. + obj.__exit__.return_value = None + return obj diff --git a/t/unit/conftest.py b/t/unit/conftest.py new file mode 100644 index 0000000..9a59124 --- /dev/null +++ b/t/unit/conftest.py @@ -0,0 +1,54 @@ +from unittest.mock import MagicMock +import pytest + +sentinel = object() + +class _patching: + + def __init__(self, monkeypatch, request): + self.monkeypatch = monkeypatch + self.request = request + + def __getattr__(self, name): + return getattr(self.monkeypatch, name) + + def __call__(self, path, value=sentinel, name=None, + new=MagicMock, **kwargs): + value = self._value_or_mock(value, new, name, path, **kwargs) + self.monkeypatch.setattr(path, value) + return value + + def _value_or_mock(self, value, new, name, path, **kwargs): + if value is sentinel: + value = new(name=name or path.rpartition('.')[2]) + for k, v in kwargs.items(): + setattr(value, k, v) + return value + + def setattr(self, target, name=sentinel, value=sentinel, **kwargs): + # alias to __call__ with the interface of pytest.monkeypatch.setattr + if value is sentinel: + value, name = name, None + return self(target, value, name=name) + + def setitem(self, dic, name, value=sentinel, new=MagicMock, **kwargs): + # same as pytest.monkeypatch.setattr but default value is MagicMock + value = self._value_or_mock(value, new, name, dic, **kwargs) + self.monkeypatch.setitem(dic, name, value) + return value + + +@pytest.fixture +def patching(monkeypatch, request): + """Monkeypath.setattr shortcut. + Example: + .. code-block:: python + def test_foo(patching): + # execv value here will be mock.MagicMock by default. + execv = patching('os.execv') + patching('sys.platform', 'darwin') # set concrete value + patching.setenv('DJANGO_SETTINGS_MODULE', 'x.settings') + # val will be of type mock.MagicMock by default + val = patching.setitem('path.to.dict', 'KEY') + """ + return _patching(monkeypatch, request) diff --git a/t/unit/test_channel.py b/t/unit/test_channel.py index 096ffcc..79eb951 100644 --- a/t/unit/test_channel.py +++ b/t/unit/test_channel.py @@ -3,7 +3,6 @@ from struct import pack from unittest.mock import ANY, MagicMock, Mock, patch import pytest -from case import ContextMock from vine import promise from amqp import spec @@ -13,6 +12,7 @@ from amqp.exceptions import (ConsumerCancelled, MessageNacked, NotFound, RecoverableConnectionError) from amqp.serialization import dumps +from t.mocks import ContextMock class test_Channel: diff --git a/t/unit/test_connection.py b/t/unit/test_connection.py index 4515585..21faebd 100644 --- a/t/unit/test_connection.py +++ b/t/unit/test_connection.py @@ -4,7 +4,6 @@ import warnings from unittest.mock import Mock, call, patch import pytest -from case import ContextMock from amqp import Connection, spec from amqp.connection import SSLError @@ -13,6 +12,8 @@ from amqp.exceptions import (ConnectionError, NotFound, from amqp.sasl import AMQPLAIN, EXTERNAL, GSSAPI, PLAIN, SASL from amqp.transport import TCPTransport +from t.mocks import ContextMock + class test_Connection: -- cgit v1.2.1