Repository: celery/celery

Issue:
5.1.2: test suite uses outdated `case` module
Looks like pytest based test suite is using `case` module which is not maintained (last release was in 2017).
```console
+ /usr/bin/pytest -ra --ignore=t/unit/backends/test_s3.py --ignore=t/unit/backends/test_mongodb.py --ignore=t/distro/test_CI_reqs.py
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.12, pytest-6.2.5, py-1.10.0, pluggy-0.13.1
benchmark: 3.4.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
Using --randomly-seed=4261956870
rootdir: /home/tkloczko/rpmbuild/BUILD/celery-5.1.2, configfile: pytest.ini
plugins: forked-1.3.0, shutil-1.7.0, virtualenv-1.7.0, expect-1.1.0, flake8-1.0.7, timeout-1.4.2, betamax-0.8.1, freezegun-0.4.2, aspectlib-1.5.2, toolbox-0.5, rerunfailures-9.1.1, requests-mock-1.9.3, cov-2.12.1, flaky-3.7.0, benchmark-3.4.1, xdist-2.3.0, pylama-7.7.1, datadir-1.3.1, regressions-2.2.0, cases-3.6.3, xprocess-0.18.1, black-0.3.12, asyncio-0.15.1, subtests-0.5.0, isort-2.0.0, hypothesis-6.14.6, mock-3.6.1, profiling-1.7.0, randomly-3.8.0, nose2pytest-1.0.8, pyfakefs-4.5.1, tornado-0.8.1, twisted-1.13.3, aiohttp-0.3.0, localserver-0.5.0, anyio-3.3.1, trio-0.7.0, Faker-8.12.2
collected 0 items / 1 error

================================================================================== ERRORS ==================================================================================
______________________________________________________________________ ERROR collecting test session _______________________________________________________________________
/usr/lib64/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1014: in _gcd_import
    ???
<frozen importlib._bootstrap>:991: in _find_and_load
    ???
<frozen importlib._bootstrap>:975: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:671: in _load_unlocked
    ???
/usr/lib/python3.8/site-packages/_pytest/assertion/rewrite.py:170: in exec_module
    exec(co, module.__dict__)
t/unit/conftest.py:10: in <module>
    from case.utils import decorator
E   ModuleNotFoundError: No module named 'case'
========================================================================= short test summary info ==========================================================================
ERROR  - ModuleNotFoundError: No module named 'case'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
============================================================================= 1 error in 0.57s =============================================================================
pytest-xprocess reminder::Be sure to terminate the started process by running 'pytest --xkill' if you have not explicitly done so in your fixture with 'xprocess.getinfo(<process_name>).terminate()'.
```



Discussion:
Hey @kloczek :wave:,
Thank you for opening an issue. We will get back to you as soon as we can.
Also, check out our [Open Collective](https://opencollective.com/celery) and consider backing us - every little helps!

We also offer priority support for our sponsors.
If you require immediate assistance please consider sponsoring us.


Resolving patch:
diff --git a/t/unit/conftest.py b/t/unit/conftest.py
--- a/t/unit/conftest.py
+++ b/t/unit/conftest.py
@@ -1,13 +1,19 @@
+import builtins
+import inspect
+import io
 import logging
 import os
+import platform
 import sys
 import threading
+import types
 import warnings
-from importlib import import_module
-from unittest.mock import Mock
+from contextlib import contextmanager
+from functools import wraps
+from importlib import import_module, reload
+from unittest.mock import MagicMock, Mock, patch
 
 import pytest
-from case.utils import decorator
 from kombu import Queue
 
 from celery.backends.cache import CacheBackend, DummyClient
@@ -39,6 +45,24 @@ class WindowsError(Exception):
 CASE_LOG_LEVEL_EFFECT = 'Test {0} modified the level of the root logger'
 CASE_LOG_HANDLER_EFFECT = 'Test {0} modified handlers for the root logger'
 
+_SIO_write = io.StringIO.write
+_SIO_init = io.StringIO.__init__
+
+SENTINEL = object()
+
+
+def noop(*args, **kwargs):
+    pass
+
+
+class WhateverIO(io.StringIO):
+
+    def __init__(self, v=None, *a, **kw):
+        _SIO_init(self, v.decode() if isinstance(v, bytes) else v, *a, **kw)
+
+    def write(self, data):
+        _SIO_write(self, data.decode() if isinstance(data, bytes) else data)
+
 
 @pytest.fixture(scope='session')
 def celery_config():
@@ -88,7 +112,7 @@ def reset_cache_backend_state(celery_app):
             backend._cache.clear()
 
 
-@decorator
+@contextmanager
 def assert_signal_called(signal, **expected):
     """Context that verifes signal is called before exiting."""
     handler = Mock()
@@ -113,7 +137,6 @@ def app(celery_app):
 def AAA_disable_multiprocessing():
     # pytest-cov breaks if a multiprocessing.Process is started,
     # so disable them completely to make sure it doesn't happen.
-    from unittest.mock import patch
     stuff = [
         'multiprocessing.Process',
         'billiard.Process',
@@ -326,3 +349,447 @@ def import_all_modules(name=__name__, file=__file__,
                     'Ignored error importing module {}: {!r}'.format(
                         module, exc,
                     )))
+
+
+@pytest.fixture
+def sleepdeprived(request):
+    """Mock sleep method in patched module to do nothing.
+
+    Example:
+        >>> import time
+        >>> @pytest.mark.sleepdeprived_patched_module(time)
+        >>> def test_foo(self, sleepdeprived):
+        >>>     pass
+    """
+    module = request.node.get_closest_marker(
+            "sleepdeprived_patched_module").args[0]
+    old_sleep, module.sleep = module.sleep, noop
+    try:
+        yield
+    finally:
+        module.sleep = old_sleep
+
+
+# Taken from
+# http://bitbucket.org/runeh/snippets/src/tip/missing_modules.py
+@pytest.fixture
+def mask_modules(request):
+    """Ban some modules from being importable inside the context
+    For example::
+        >>> @pytest.mark.masked_modules('gevent.monkey')
+        >>> def test_foo(self, mask_modules):
+        ...     try:
+        ...         import sys
+        ...     except ImportError:
+        ...         print('sys not found')
+        sys not found
+    """
+    realimport = builtins.__import__
+    modnames = request.node.get_closest_marker("masked_modules").args
+
+    def myimp(name, *args, **kwargs):
+        if name in modnames:
+            raise ImportError('No module named %s' % name)
+        else:
+            return realimport(name, *args, **kwargs)
+
+    builtins.__import__ = myimp
+    try:
+        yield
+    finally:
+        builtins.__import__ = realimport
+
+
+@pytest.fixture
+def environ(request):
+    """Mock environment variable value.
+    Example::
+        >>> @pytest.mark.patched_environ('DJANGO_SETTINGS_MODULE', 'proj.settings')
+        >>> def test_other_settings(self, environ):
+        ...    ...
+    """
+    env_name, env_value = request.node.get_closest_marker("patched_environ").args
+    prev_val = os.environ.get(env_name, SENTINEL)
+    os.environ[env_name] = env_value
+    try:
+        yield
+    finally:
+        if prev_val is SENTINEL:
+            os.environ.pop(env_name, None)
+        else:
+            os.environ[env_name] = prev_val
+
+
+def replace_module_value(module, name, value=None):
+    """Mock module value, given a module, attribute name and value.
+
+    Example::
+
+        >>> replace_module_value(module, 'CONSTANT', 3.03)
+    """
+    has_prev = hasattr(module, name)
+    prev = getattr(module, name, None)
+    if value:
+        setattr(module, name, value)
+    else:
+        try:
+            delattr(module, name)
+        except AttributeError:
+            pass
+    try:
+        yield
+    finally:
+        if prev is not None:
+            setattr(module, name, prev)
+        if not has_prev:
+            try:
+                delattr(module, name)
+            except AttributeError:
+                pass
+
+
+@contextmanager
+def platform_pyimp(value=None):
+    """Mock :data:`platform.python_implementation`
+    Example::
+        >>> with platform_pyimp('PyPy'):
+        ...     ...
+    """
+    yield from replace_module_value(platform, 'python_implementation', value)
+
+
+@contextmanager
+def sys_platform(value=None):
+    """Mock :data:`sys.platform`
+
+    Example::
+        >>> mock.sys_platform('darwin'):
+        ...     ...
+    """
+    prev, sys.platform = sys.platform, value
+    try:
+        yield
+    finally:
+        sys.platform = prev
+
+
+@contextmanager
+def pypy_version(value=None):
+    """Mock :data:`sys.pypy_version_info`
+
+    Example::
+        >>> with pypy_version((3, 6, 1)):
+        ...     ...
+    """
+    yield from replace_module_value(sys, 'pypy_version_info', value)
+
+
+def _restore_logging():
+    outs = sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__
+    root = logging.getLogger()
+    level = root.level
+    handlers = root.handlers
+
+    try:
+        yield
+    finally:
+        sys.stdout, sys.stderr, sys.__stdout__, sys.__stderr__ = outs
+        root.level = level
+        root.handlers[:] = handlers
+
+
+@contextmanager
+def restore_logging_context_manager():
+    """Restore root logger handlers after test returns.
+    Example::
+        >>> with restore_logging_context_manager():
+        ...     setup_logging()
+    """
+    yield from _restore_logging()
+
+
+@pytest.fixture
+def restore_logging(request):
+    """Restore root logger handlers after test returns.
+    Example::
+        >>> def test_foo(self, restore_logging):
+        ...     setup_logging()
+    """
+    yield from _restore_logging()
+
+
+@pytest.fixture
+def module(request):
+    """Mock one or modules such that every attribute is a :class:`Mock`."""
+    yield from _module(*request.node.get_closest_marker("patched_module").args)
+
+
+@contextmanager
+def module_context_manager(*names):
+    """Mock one or modules such that every attribute is a :class:`Mock`."""
+    yield from _module(*names)
+
+
+def _module(*names):
+    prev = {}
+
+    class MockModule(types.ModuleType):
+
+        def __getattr__(self, attr):
+            setattr(self, attr, Mock())
+            return types.ModuleType.__getattribute__(self, attr)
+
+    mods = []
+    for name in names:
+        try:
+            prev[name] = sys.modules[name]
+        except KeyError:
+            pass
+        mod = sys.modules[name] = MockModule(name)
+        mods.append(mod)
+    try:
+        yield mods
+    finally:
+        for name in names:
+            try:
+                sys.modules[name] = prev[name]
+            except KeyError:
+                try:
+                    del(sys.modules[name])
+                except KeyError:
+                    pass
+
+
+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 object(self, target, attribute, *args, **kwargs):
+        return _wrap_context(
+            patch.object(target, attribute, *args, **kwargs),
+            self.request)
+
+    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
+
+    def modules(self, *mods):
+        modules = []
+        for mod in mods:
+            mod = mod.split('.')
+            modules.extend(reversed([
+                '.'.join(mod[:-i] if i else mod) for i in range(len(mod))
+            ]))
+        modules = sorted(set(modules))
+        return _wrap_context(module_context_manager(*modules), self.request)
+
+
+def _wrap_context(context, request):
+    ret = context.__enter__()
+
+    def fin():
+        context.__exit__(*sys.exc_info())
+    request.addfinalizer(fin)
+    return ret
+
+
+@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)
+
+
+@contextmanager
+def stdouts():
+    """Override `sys.stdout` and `sys.stderr` with `StringIO`
+    instances.
+        >>> with conftest.stdouts() as (stdout, stderr):
+        ...     something()
+        ...     self.assertIn('foo', stdout.getvalue())
+    """
+    prev_out, prev_err = sys.stdout, sys.stderr
+    prev_rout, prev_rerr = sys.__stdout__, sys.__stderr__
+    mystdout, mystderr = WhateverIO(), WhateverIO()
+    sys.stdout = sys.__stdout__ = mystdout
+    sys.stderr = sys.__stderr__ = mystderr
+
+    try:
+        yield mystdout, mystderr
+    finally:
+        sys.stdout = prev_out
+        sys.stderr = prev_err
+        sys.__stdout__ = prev_rout
+        sys.__stderr__ = prev_rerr
+
+
+@contextmanager
+def reset_modules(*modules):
+    """Remove modules from :data:`sys.modules` by name,
+    and reset back again when the test/context returns.
+    Example::
+        >>> with conftest.reset_modules('celery.result', 'celery.app.base'):
+        ...     pass
+    """
+    prev = {
+        k: sys.modules.pop(k) for k in modules if k in sys.modules
+    }
+
+    try:
+        for k in modules:
+            reload(import_module(k))
+        yield
+    finally:
+        sys.modules.update(prev)
+
+
+def get_logger_handlers(logger):
+    return [
+        h for h in logger.handlers
+        if not isinstance(h, logging.NullHandler)
+    ]
+
+
+@contextmanager
+def wrap_logger(logger, loglevel=logging.ERROR):
+    """Wrap :class:`logging.Logger` with a StringIO() handler.
+    yields a StringIO handle.
+    Example::
+        >>> with conftest.wrap_logger(logger, loglevel=logging.DEBUG) as sio:
+        ...     ...
+        ...     sio.getvalue()
+    """
+    old_handlers = get_logger_handlers(logger)
+    sio = WhateverIO()
+    siohandler = logging.StreamHandler(sio)
+    logger.handlers = [siohandler]
+
+    try:
+        yield sio
+    finally:
+        logger.handlers = old_handlers
+
+
+@contextmanager
+def _mock_context(mock):
+    context = mock.return_value = Mock()
+    context.__enter__ = Mock()
+    context.__exit__ = Mock()
+
+    def on_exit(*x):
+        if x[0]:
+            raise x[0] from x[1]
+    context.__exit__.side_effect = on_exit
+    context.__enter__.return_value = context
+    try:
+        yield context
+    finally:
+        context.reset()
+
+
+@contextmanager
+def open(side_effect=None):
+    """Patch builtins.open so that it returns StringIO object.
+    :param side_effect: Additional side effect for when the open context
+        is entered.
+    Example::
+        >>> with mock.open(io.BytesIO) as open_fh:
+        ...     something_opening_and_writing_bytes_to_a_file()
+        ...     self.assertIn(b'foo', open_fh.getvalue())
+    """
+    with patch('builtins.open') as open_:
+        with _mock_context(open_) as context:
+            if side_effect is not None:
+                context.__enter__.side_effect = side_effect
+            val = context.__enter__.return_value = WhateverIO()
+            val.__exit__ = Mock()
+            yield val
+
+
+@contextmanager
+def module_exists(*modules):
+    """Patch one or more modules to ensure they exist.
+    A module name with multiple paths (e.g. gevent.monkey) will
+    ensure all parent modules are also patched (``gevent`` +
+    ``gevent.monkey``).
+    Example::
+        >>> with conftest.module_exists('gevent.monkey'):
+        ...     gevent.monkey.patch_all = Mock(name='patch_all')
+        ...     ...
+    """
+    gen = []
+    old_modules = []
+    for module in modules:
+        if isinstance(module, str):
+            module = types.ModuleType(module)
+        gen.append(module)
+        if module.__name__ in sys.modules:
+            old_modules.append(sys.modules[module.__name__])
+        sys.modules[module.__name__] = module
+        name = module.__name__
+        if '.' in name:
+            parent, _, attr = name.rpartition('.')
+            setattr(sys.modules[parent], attr, module)
+    try:
+        yield
+    finally:
+        for module in gen:
+            sys.modules.pop(module.__name__, None)
+        for module in old_modules:
+            sys.modules[module.__name__] = module
+
+
+def _bind(f, o):
+    @wraps(f)
+    def bound_meth(*fargs, **fkwargs):
+        return f(o, *fargs, **fkwargs)
+    return bound_meth
+
+
+class MockCallbacks:
+
+    def __new__(cls, *args, **kwargs):
+        r = Mock(name=cls.__name__)
+        cls.__init__(r, *args, **kwargs)
+        for key, value in vars(cls).items():
+            if key not in ('__dict__', '__weakref__', '__new__', '__init__'):
+                if inspect.ismethod(value) or inspect.isfunction(value):
+                    r.__getattr__(key).side_effect = _bind(value, r)
+                else:
+                    r.__setattr__(key, value)
+        return r


Test patch:
diff --git a/celery/contrib/testing/mocks.py b/celery/contrib/testing/mocks.py
--- a/celery/contrib/testing/mocks.py
+++ b/celery/contrib/testing/mocks.py
@@ -2,15 +2,11 @@
 import numbers
 from datetime import datetime, timedelta
 from typing import Any, Mapping, Sequence
+from unittest.mock import Mock
 
 from celery import Celery
 from celery.canvas import Signature
 
-try:
-    from case import Mock
-except ImportError:
-    from unittest.mock import Mock
-
 
 def TaskMessage(
     name,  # type: str
@@ -113,3 +109,29 @@ def task_message_from_sig(app, sig, utc=True, TaskMessage=TaskMessage):
         utc=utc,
         **sig.options
     )
+
+
+class _ContextMock(Mock):
+    """Dummy class implementing __enter__ and __exit__.
+
+    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/requirements/test.txt b/requirements/test.txt
--- a/requirements/test.txt
+++ b/requirements/test.txt
@@ -1,4 +1,3 @@
-case>=1.3.1
 pytest~=6.2
 pytest-celery
 pytest-subtests
diff --git a/t/unit/app/test_app.py b/t/unit/app/test_app.py
--- a/t/unit/app/test_app.py
+++ b/t/unit/app/test_app.py
@@ -9,7 +9,6 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import ContextMock, mock
 from vine import promise
 
 from celery import Celery, _state
@@ -18,6 +17,7 @@
 from celery.app import base as _appbase
 from celery.app import defaults
 from celery.backends.base import Backend
+from celery.contrib.testing.mocks import ContextMock
 from celery.exceptions import ImproperlyConfigured
 from celery.loaders.base import unconfigured
 from celery.platforms import pyimplementation
@@ -25,6 +25,7 @@
 from celery.utils.objects import Bunch
 from celery.utils.serialization import pickle
 from celery.utils.time import localize, timezone, to_utc
+from t.unit import conftest
 
 THIS_IS_A_KEY = 'this is a value'
 
@@ -915,10 +916,10 @@ def add(x, y):
         assert 'add1' in self.app.conf.beat_schedule
         assert 'add2' in self.app.conf.beat_schedule
 
-    def test_pool_no_multiprocessing(self):
-        with mock.mask_modules('multiprocessing.util'):
-            pool = self.app.pool
-            assert pool is self.app._pool
+    @pytest.mark.masked_modules('multiprocessing.util')
+    def test_pool_no_multiprocessing(self, mask_modules):
+        pool = self.app.pool
+        assert pool is self.app._pool
 
     def test_bugreport(self):
         assert self.app.bugreport()
@@ -1078,26 +1079,26 @@ def test_enable_disable_trace(self):
 class test_pyimplementation:
 
     def test_platform_python_implementation(self):
-        with mock.platform_pyimp(lambda: 'Xython'):
+        with conftest.platform_pyimp(lambda: 'Xython'):
             assert pyimplementation() == 'Xython'
 
     def test_platform_jython(self):
-        with mock.platform_pyimp():
-            with mock.sys_platform('java 1.6.51'):
+        with conftest.platform_pyimp():
+            with conftest.sys_platform('java 1.6.51'):
                 assert 'Jython' in pyimplementation()
 
     def test_platform_pypy(self):
-        with mock.platform_pyimp():
-            with mock.sys_platform('darwin'):
-                with mock.pypy_version((1, 4, 3)):
+        with conftest.platform_pyimp():
+            with conftest.sys_platform('darwin'):
+                with conftest.pypy_version((1, 4, 3)):
                     assert 'PyPy' in pyimplementation()
-                with mock.pypy_version((1, 4, 3, 'a4')):
+                with conftest.pypy_version((1, 4, 3, 'a4')):
                     assert 'PyPy' in pyimplementation()
 
     def test_platform_fallback(self):
-        with mock.platform_pyimp():
-            with mock.sys_platform('darwin'):
-                with mock.pypy_version():
+        with conftest.platform_pyimp():
+            with conftest.sys_platform('darwin'):
+                with conftest.pypy_version():
                     assert 'CPython' == pyimplementation()
 
 
diff --git a/t/unit/app/test_builtins.py b/t/unit/app/test_builtins.py
--- a/t/unit/app/test_builtins.py
+++ b/t/unit/app/test_builtins.py
@@ -1,10 +1,10 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import ContextMock
 
 from celery import chord, group
 from celery.app import builtins
+from celery.contrib.testing.mocks import ContextMock
 from celery.utils.functional import pass1
 
 
diff --git a/t/unit/app/test_loaders.py b/t/unit/app/test_loaders.py
--- a/t/unit/app/test_loaders.py
+++ b/t/unit/app/test_loaders.py
@@ -4,7 +4,6 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 
 from celery import loaders
 from celery.exceptions import NotConfigured
@@ -120,8 +119,8 @@ def test_read_configuration_not_a_package(self, find_module):
             l.read_configuration(fail_silently=False)
 
     @patch('celery.loaders.base.find_module')
-    @mock.environ('CELERY_CONFIG_MODULE', 'celeryconfig.py')
-    def test_read_configuration_py_in_name(self, find_module):
+    @pytest.mark.patched_environ('CELERY_CONFIG_MODULE', 'celeryconfig.py')
+    def test_read_configuration_py_in_name(self, find_module, environ):
         find_module.side_effect = NotAPackage()
         l = default.Loader(app=self.app)
         with pytest.raises(NotAPackage):
diff --git a/t/unit/app/test_log.py b/t/unit/app/test_log.py
--- a/t/unit/app/test_log.py
+++ b/t/unit/app/test_log.py
@@ -6,8 +6,6 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
-from case.utils import get_logger_handlers
 
 from celery import signals, uuid
 from celery.app.log import TaskFormatter
@@ -15,6 +13,7 @@
                               get_task_logger, in_sighandler)
 from celery.utils.log import logger as base_logger
 from celery.utils.log import logger_isa, task_logger
+from t.unit import conftest
 
 
 class test_TaskFormatter:
@@ -165,12 +164,10 @@ def test_get_logger_root(self):
         logger = get_logger(base_logger.name)
         assert logger.parent is logging.root
 
-    @mock.restore_logging()
-    def test_setup_logging_subsystem_misc(self):
+    def test_setup_logging_subsystem_misc(self, restore_logging):
         self.app.log.setup_logging_subsystem(loglevel=None)
 
-    @mock.restore_logging()
-    def test_setup_logging_subsystem_misc2(self):
+    def test_setup_logging_subsystem_misc2(self, restore_logging):
         self.app.conf.worker_hijack_root_logger = True
         self.app.log.setup_logging_subsystem()
 
@@ -183,18 +180,15 @@ def test_configure_logger(self):
         self.app.log._configure_logger(None, sys.stderr, None, '', False)
         logger.handlers[:] = []
 
-    @mock.restore_logging()
-    def test_setup_logging_subsystem_colorize(self):
+    def test_setup_logging_subsystem_colorize(self, restore_logging):
         self.app.log.setup_logging_subsystem(colorize=None)
         self.app.log.setup_logging_subsystem(colorize=True)
 
-    @mock.restore_logging()
-    def test_setup_logging_subsystem_no_mputil(self):
-        with mock.mask_modules('billiard.util'):
-            self.app.log.setup_logging_subsystem()
+    @pytest.mark.masked_modules('billiard.util')
+    def test_setup_logging_subsystem_no_mputil(self, restore_logging, mask_modules):
+        self.app.log.setup_logging_subsystem()
 
-    @mock.restore_logging()
-    def test_setup_logger(self):
+    def test_setup_logger(self, restore_logging):
         logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
                                    root=False, colorize=True)
         logger.handlers = []
@@ -202,16 +196,14 @@ def test_setup_logger(self):
         logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
                                    root=False, colorize=None)
         # setup_logger logs to stderr without logfile argument.
-        assert (get_logger_handlers(logger)[0].stream is
+        assert (conftest.get_logger_handlers(logger)[0].stream is
                 sys.__stderr__)
 
-    @mock.restore_logging()
-    def test_setup_logger_no_handlers_stream(self):
+    def test_setup_logger_no_handlers_stream(self, restore_logging):
         l = self.get_logger()
         l.handlers = []
 
-        with mock.stdouts() as outs:
-            stdout, stderr = outs
+        with conftest.stdouts() as (stdout, stderr):
             l = self.setup_logger(logfile=sys.stderr,
                                   loglevel=logging.INFO, root=False)
             l.info('The quick brown fox...')
@@ -221,7 +213,7 @@ def test_setup_logger_no_handlers_stream(self):
     def test_setup_logger_no_handlers_file(self, *args):
         tempfile = mktemp(suffix='unittest', prefix='celery')
         with patch('builtins.open') as osopen:
-            with mock.restore_logging():
+            with conftest.restore_logging_context_manager():
                 files = defaultdict(StringIO)
 
                 def open_file(filename, *args, **kwargs):
@@ -236,16 +228,15 @@ def open_file(filename, *args, **kwargs):
                 l = self.setup_logger(
                     logfile=tempfile, loglevel=logging.INFO, root=False,
                 )
-                assert isinstance(get_logger_handlers(l)[0],
+                assert isinstance(conftest.get_logger_handlers(l)[0],
                                   logging.FileHandler)
                 assert tempfile in files
 
-    @mock.restore_logging()
-    def test_redirect_stdouts(self):
+    def test_redirect_stdouts(self, restore_logging):
         logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
                                    root=False)
         try:
-            with mock.wrap_logger(logger) as sio:
+            with conftest.wrap_logger(logger) as sio:
                 self.app.log.redirect_stdouts_to_logger(
                     logger, loglevel=logging.ERROR,
                 )
@@ -257,12 +248,11 @@ def test_redirect_stdouts(self):
         finally:
             sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__
 
-    @mock.restore_logging()
-    def test_logging_proxy(self):
+    def test_logging_proxy(self, restore_logging):
         logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
                                    root=False)
 
-        with mock.wrap_logger(logger) as sio:
+        with conftest.wrap_logger(logger) as sio:
             p = LoggingProxy(logger, loglevel=logging.ERROR)
             p.close()
             p.write('foo')
@@ -281,17 +271,16 @@ def test_logging_proxy(self):
             p.close()
             assert not p.isatty()
 
-            with mock.stdouts() as (stdout, stderr):
+            with conftest.stdouts() as (stdout, stderr):
                 with in_sighandler():
                     p.write('foo')
                     assert stderr.getvalue()
 
-    @mock.restore_logging()
-    def test_logging_proxy_bytes(self):
+    def test_logging_proxy_bytes(self, restore_logging):
         logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
                                    root=False)
 
-        with mock.wrap_logger(logger) as sio:
+        with conftest.wrap_logger(logger) as sio:
             p = LoggingProxy(logger, loglevel=logging.ERROR)
             p.close()
             p.write(b'foo')
@@ -306,13 +295,12 @@ def test_logging_proxy_bytes(self):
             p.close()
             assert not p.isatty()
 
-            with mock.stdouts() as (stdout, stderr):
+            with conftest.stdouts() as (stdout, stderr):
                 with in_sighandler():
                     p.write(b'foo')
                     assert stderr.getvalue()
 
-    @mock.restore_logging()
-    def test_logging_proxy_recurse_protection(self):
+    def test_logging_proxy_recurse_protection(self, restore_logging):
         logger = self.setup_logger(loglevel=logging.ERROR, logfile=None,
                                    root=False)
         p = LoggingProxy(logger, loglevel=logging.ERROR)
diff --git a/t/unit/app/test_schedules.py b/t/unit/app/test_schedules.py
--- a/t/unit/app/test_schedules.py
+++ b/t/unit/app/test_schedules.py
@@ -2,16 +2,16 @@
 from contextlib import contextmanager
 from datetime import datetime, timedelta
 from pickle import dumps, loads
+from unittest import TestCase
 from unittest.mock import Mock
 
 import pytest
 import pytz
-from case import Case
 
 from celery.schedules import (ParseException, crontab, crontab_parser,
                               schedule, solar)
 
-assertions = Case('__init__')
+assertions = TestCase('__init__')
 
 
 @contextmanager
diff --git a/t/unit/backends/test_cache.py b/t/unit/backends/test_cache.py
--- a/t/unit/backends/test_cache.py
+++ b/t/unit/backends/test_cache.py
@@ -4,12 +4,12 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 from kombu.utils.encoding import ensure_bytes, str_to_bytes
 
 from celery import signature, states, uuid
 from celery.backends.cache import CacheBackend, DummyClient, backends
 from celery.exceptions import ImproperlyConfigured
+from t.unit import conftest
 
 
 class SomeClass:
@@ -148,7 +148,7 @@ def test_regression_worker_startup_info(self):
             'cache+memcached://127.0.0.1:11211;127.0.0.2:11211;127.0.0.3/'
         )
         worker = self.app.Worker()
-        with mock.stdouts():
+        with conftest.stdouts():
             worker.on_start()
             assert worker.startup_info()
 
@@ -201,31 +201,31 @@ class test_get_best_memcache(MockCacheMixin):
 
     def test_pylibmc(self):
         with self.mock_pylibmc():
-            with mock.reset_modules('celery.backends.cache'):
+            with conftest.reset_modules('celery.backends.cache'):
                 from celery.backends import cache
                 cache._imp = [None]
                 assert cache.get_best_memcache()[0].__module__ == 'pylibmc'
 
-    def test_memcache(self):
+    @pytest.mark.masked_modules('pylibmc')
+    def test_memcache(self, mask_modules):
         with self.mock_memcache():
-            with mock.reset_modules('celery.backends.cache'):
-                with mock.mask_modules('pylibmc'):
-                    from celery.backends import cache
-                    cache._imp = [None]
-                    assert (cache.get_best_memcache()[0]().__module__ ==
-                            'memcache')
-
-    def test_no_implementations(self):
-        with mock.mask_modules('pylibmc', 'memcache'):
-            with mock.reset_modules('celery.backends.cache'):
+            with conftest.reset_modules('celery.backends.cache'):
                 from celery.backends import cache
                 cache._imp = [None]
-                with pytest.raises(ImproperlyConfigured):
-                    cache.get_best_memcache()
+                assert (cache.get_best_memcache()[0]().__module__ ==
+                        'memcache')
+
+    @pytest.mark.masked_modules('pylibmc', 'memcache')
+    def test_no_implementations(self, mask_modules):
+        with conftest.reset_modules('celery.backends.cache'):
+            from celery.backends import cache
+            cache._imp = [None]
+            with pytest.raises(ImproperlyConfigured):
+                cache.get_best_memcache()
 
     def test_cached(self):
         with self.mock_pylibmc():
-            with mock.reset_modules('celery.backends.cache'):
+            with conftest.reset_modules('celery.backends.cache'):
                 from celery.backends import cache
                 cache._imp = [None]
                 cache.get_best_memcache()[0](behaviors={'foo': 'bar'})
@@ -241,30 +241,30 @@ def test_backends(self):
 
 class test_memcache_key(MockCacheMixin):
 
-    def test_memcache_unicode_key(self):
+    @pytest.mark.masked_modules('pylibmc')
+    def test_memcache_unicode_key(self, mask_modules):
         with self.mock_memcache():
-            with mock.reset_modules('celery.backends.cache'):
-                with mock.mask_modules('pylibmc'):
-                    from celery.backends import cache
-                    cache._imp = [None]
-                    task_id, result = str(uuid()), 42
-                    b = cache.CacheBackend(backend='memcache', app=self.app)
-                    b.store_result(task_id, result, state=states.SUCCESS)
-                    assert b.get_result(task_id) == result
-
-    def test_memcache_bytes_key(self):
+            with conftest.reset_modules('celery.backends.cache'):
+                from celery.backends import cache
+                cache._imp = [None]
+                task_id, result = str(uuid()), 42
+                b = cache.CacheBackend(backend='memcache', app=self.app)
+                b.store_result(task_id, result, state=states.SUCCESS)
+                assert b.get_result(task_id) == result
+
+    @pytest.mark.masked_modules('pylibmc')
+    def test_memcache_bytes_key(self, mask_modules):
         with self.mock_memcache():
-            with mock.reset_modules('celery.backends.cache'):
-                with mock.mask_modules('pylibmc'):
-                    from celery.backends import cache
-                    cache._imp = [None]
-                    task_id, result = str_to_bytes(uuid()), 42
-                    b = cache.CacheBackend(backend='memcache', app=self.app)
-                    b.store_result(task_id, result, state=states.SUCCESS)
-                    assert b.get_result(task_id) == result
+            with conftest.reset_modules('celery.backends.cache'):
+                from celery.backends import cache
+                cache._imp = [None]
+                task_id, result = str_to_bytes(uuid()), 42
+                b = cache.CacheBackend(backend='memcache', app=self.app)
+                b.store_result(task_id, result, state=states.SUCCESS)
+                assert b.get_result(task_id) == result
 
     def test_pylibmc_unicode_key(self):
-        with mock.reset_modules('celery.backends.cache'):
+        with conftest.reset_modules('celery.backends.cache'):
             with self.mock_pylibmc():
                 from celery.backends import cache
                 cache._imp = [None]
@@ -274,7 +274,7 @@ def test_pylibmc_unicode_key(self):
                 assert b.get_result(task_id) == result
 
     def test_pylibmc_bytes_key(self):
-        with mock.reset_modules('celery.backends.cache'):
+        with conftest.reset_modules('celery.backends.cache'):
             with self.mock_pylibmc():
                 from celery.backends import cache
                 cache._imp = [None]
diff --git a/t/unit/backends/test_cassandra.py b/t/unit/backends/test_cassandra.py
--- a/t/unit/backends/test_cassandra.py
+++ b/t/unit/backends/test_cassandra.py
@@ -3,7 +3,6 @@
 from unittest.mock import Mock
 
 import pytest
-from case import mock
 
 from celery import states
 from celery.exceptions import ImproperlyConfigured
@@ -17,7 +16,6 @@
 ]
 
 
-@mock.module(*CASSANDRA_MODULES)
 class test_CassandraBackend:
 
     def setup(self):
@@ -27,7 +25,8 @@ def setup(self):
             cassandra_table='task_results',
         )
 
-    def test_init_no_cassandra(self, *modules):
+    @pytest.mark.patched_module(*CASSANDRA_MODULES)
+    def test_init_no_cassandra(self, module):
         # should raise ImproperlyConfigured when no python-driver
         # installed.
         from celery.backends import cassandra as mod
@@ -38,7 +37,8 @@ def test_init_no_cassandra(self, *modules):
         finally:
             mod.cassandra = prev
 
-    def test_init_with_and_without_LOCAL_QUROM(self, *modules):
+    @pytest.mark.patched_module(*CASSANDRA_MODULES)
+    def test_init_with_and_without_LOCAL_QUROM(self, module):
         from celery.backends import cassandra as mod
         mod.cassandra = Mock()
 
@@ -60,12 +60,14 @@ def test_init_with_and_without_LOCAL_QUROM(self, *modules):
                 app=self.app, keyspace='b', column_family='c',
             )
 
+    @pytest.mark.patched_module(*CASSANDRA_MODULES)
     @pytest.mark.usefixtures('depends_on_current_app')
-    def test_reduce(self, *modules):
+    def test_reduce(self, module):
         from celery.backends.cassandra import CassandraBackend
         assert loads(dumps(CassandraBackend(app=self.app)))
 
-    def test_get_task_meta_for(self, *modules):
+    @pytest.mark.patched_module(*CASSANDRA_MODULES)
+    def test_get_task_meta_for(self, module):
         from celery.backends import cassandra as mod
         mod.cassandra = Mock()
 
@@ -95,7 +97,8 @@ def test_as_uri(self):
         x.as_uri()
         x.as_uri(include_password=False)
 
-    def test_store_result(self, *modules):
+    @pytest.mark.patched_module(*CASSANDRA_MODULES)
+    def test_store_result(self, module):
         from celery.backends import cassandra as mod
         mod.cassandra = Mock()
 
diff --git a/t/unit/backends/test_mongodb.py b/t/unit/backends/test_mongodb.py
--- a/t/unit/backends/test_mongodb.py
+++ b/t/unit/backends/test_mongodb.py
@@ -4,7 +4,6 @@
 
 import pytest
 import pytz
-from case import mock
 from kombu.exceptions import EncodeError
 
 try:
@@ -15,6 +14,7 @@
 from celery import states, uuid
 from celery.backends.mongodb import Binary, InvalidDocument, MongoBackend
 from celery.exceptions import ImproperlyConfigured
+from t.unit import conftest
 
 COLLECTION = 'taskmeta_celery'
 TASK_ID = uuid()
@@ -529,7 +529,7 @@ def test_regression_worker_startup_info(self):
             '/work4us?replicaSet=rs&ssl=true'
         )
         worker = self.app.Worker()
-        with mock.stdouts():
+        with conftest.stdouts():
             worker.on_start()
             assert worker.startup_info()
 
diff --git a/t/unit/backends/test_redis.py b/t/unit/backends/test_redis.py
--- a/t/unit/backends/test_redis.py
+++ b/t/unit/backends/test_redis.py
@@ -8,14 +8,15 @@
 from unittest.mock import ANY, Mock, call, patch
 
 import pytest
-from case import ContextMock, mock
 
 from celery import signature, states, uuid
 from celery.canvas import Signature
+from celery.contrib.testing.mocks import ContextMock
 from celery.exceptions import (BackendStoreError, ChordError,
                                ImproperlyConfigured)
 from celery.result import AsyncResult, GroupResult
 from celery.utils.collections import AttributeDict
+from t.unit import conftest
 
 
 def raise_on_second_call(mock, exc, *retval):
@@ -61,7 +62,7 @@ def execute(self):
         return [step(*a, **kw) for step, a, kw in self.steps]
 
 
-class PubSub(mock.MockCallbacks):
+class PubSub(conftest.MockCallbacks):
     def __init__(self, ignore_subscribe_messages=False):
         self._subscribed_to = set()
 
@@ -78,7 +79,7 @@ def get_message(self, timeout=None):
         pass
 
 
-class Redis(mock.MockCallbacks):
+class Redis(conftest.MockCallbacks):
     Connection = Connection
     Pipeline = Pipeline
     pubsub = PubSub
@@ -158,7 +159,7 @@ def zcount(self, key, min_, max_):
         return len(self.zrangebyscore(key, min_, max_))
 
 
-class Sentinel(mock.MockCallbacks):
+class Sentinel(conftest.MockCallbacks):
     def __init__(self, sentinels, min_other_sentinels=0, sentinel_kwargs=None,
                  **connection_kwargs):
         self.sentinel_kwargs = sentinel_kwargs
diff --git a/t/unit/concurrency/test_prefork.py b/t/unit/concurrency/test_prefork.py
--- a/t/unit/concurrency/test_prefork.py
+++ b/t/unit/concurrency/test_prefork.py
@@ -5,7 +5,6 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 
 import t.skip
 from celery.app.defaults import DEFAULTS
@@ -64,55 +63,53 @@ def Loader(*args, **kwargs):
         return loader
 
     @patch('celery.platforms.signals')
-    def test_process_initializer(self, _signals, set_mp_process_title):
-        with mock.restore_logging():
-            from celery import signals
-            from celery._state import _tls
-            from celery.concurrency.prefork import (WORKER_SIGIGNORE,
-                                                    WORKER_SIGRESET,
-                                                    process_initializer)
-            on_worker_process_init = Mock()
-            signals.worker_process_init.connect(on_worker_process_init)
-
-            with self.Celery(loader=self.Loader) as app:
-                app.conf = AttributeDict(DEFAULTS)
-                process_initializer(app, 'awesome.worker.com')
-                _signals.ignore.assert_any_call(*WORKER_SIGIGNORE)
-                _signals.reset.assert_any_call(*WORKER_SIGRESET)
-                assert app.loader.init_worker.call_count
-                on_worker_process_init.assert_called()
-                assert _tls.current_app is app
-                set_mp_process_title.assert_called_with(
-                    'celeryd', hostname='awesome.worker.com',
-                )
-
-                with patch('celery.app.trace.setup_worker_optimizations') as S:
-                    os.environ['FORKED_BY_MULTIPROCESSING'] = '1'
-                    try:
-                        process_initializer(app, 'luke.worker.com')
-                        S.assert_called_with(app, 'luke.worker.com')
-                    finally:
-                        os.environ.pop('FORKED_BY_MULTIPROCESSING', None)
+    def test_process_initializer(self, _signals, set_mp_process_title, restore_logging):
+        from celery import signals
+        from celery._state import _tls
+        from celery.concurrency.prefork import (WORKER_SIGIGNORE,
+                                                WORKER_SIGRESET,
+                                                process_initializer)
+        on_worker_process_init = Mock()
+        signals.worker_process_init.connect(on_worker_process_init)
+
+        with self.Celery(loader=self.Loader) as app:
+            app.conf = AttributeDict(DEFAULTS)
+            process_initializer(app, 'awesome.worker.com')
+            _signals.ignore.assert_any_call(*WORKER_SIGIGNORE)
+            _signals.reset.assert_any_call(*WORKER_SIGRESET)
+            assert app.loader.init_worker.call_count
+            on_worker_process_init.assert_called()
+            assert _tls.current_app is app
+            set_mp_process_title.assert_called_with(
+                'celeryd', hostname='awesome.worker.com',
+            )
 
-                os.environ['CELERY_LOG_FILE'] = 'worker%I.log'
-                app.log.setup = Mock(name='log_setup')
+            with patch('celery.app.trace.setup_worker_optimizations') as S:
+                os.environ['FORKED_BY_MULTIPROCESSING'] = '1'
                 try:
                     process_initializer(app, 'luke.worker.com')
+                    S.assert_called_with(app, 'luke.worker.com')
                 finally:
-                    os.environ.pop('CELERY_LOG_FILE', None)
+                    os.environ.pop('FORKED_BY_MULTIPROCESSING', None)
+
+            os.environ['CELERY_LOG_FILE'] = 'worker%I.log'
+            app.log.setup = Mock(name='log_setup')
+            try:
+                process_initializer(app, 'luke.worker.com')
+            finally:
+                os.environ.pop('CELERY_LOG_FILE', None)
 
     @patch('celery.platforms.set_pdeathsig')
-    def test_pdeath_sig(self, _set_pdeathsig, set_mp_process_title):
-        with mock.restore_logging():
-            from celery import signals
-            on_worker_process_init = Mock()
-            signals.worker_process_init.connect(on_worker_process_init)
-            from celery.concurrency.prefork import process_initializer
-
-            with self.Celery(loader=self.Loader) as app:
-                app.conf = AttributeDict(DEFAULTS)
-                process_initializer(app, 'awesome.worker.com')
-            _set_pdeathsig.assert_called_once_with('SIGKILL')
+    def test_pdeath_sig(self, _set_pdeathsig, set_mp_process_title, restore_logging):
+        from celery import signals
+        on_worker_process_init = Mock()
+        signals.worker_process_init.connect(on_worker_process_init)
+        from celery.concurrency.prefork import process_initializer
+
+        with self.Celery(loader=self.Loader) as app:
+            app.conf = AttributeDict(DEFAULTS)
+            process_initializer(app, 'awesome.worker.com')
+        _set_pdeathsig.assert_called_once_with('SIGKILL')
 
 
 class test_process_destructor:
diff --git a/t/unit/contrib/test_migrate.py b/t/unit/contrib/test_migrate.py
--- a/t/unit/contrib/test_migrate.py
+++ b/t/unit/contrib/test_migrate.py
@@ -3,7 +3,6 @@
 
 import pytest
 from amqp import ChannelError
-from case import mock
 from kombu import Connection, Exchange, Producer, Queue
 from kombu.transport.virtual import QoS
 from kombu.utils.encoding import ensure_bytes
@@ -14,6 +13,7 @@
                                     migrate_tasks, move, move_by_idmap,
                                     move_by_taskmap, move_task_by_id,
                                     start_filter, task_id_eq, task_id_in)
+from t.unit import conftest
 
 # hack to ignore error at shutdown
 QoS.restore_at_shutdown = False
@@ -203,7 +203,7 @@ def test_maybe_queue():
 
 
 def test_filter_status():
-    with mock.stdouts() as (stdout, stderr):
+    with conftest.stdouts() as (stdout, stderr):
         filter_status(State(), {'id': '1', 'task': 'add'}, Mock())
         assert stdout.getvalue()
 
diff --git a/t/unit/events/test_snapshot.py b/t/unit/events/test_snapshot.py
--- a/t/unit/events/test_snapshot.py
+++ b/t/unit/events/test_snapshot.py
@@ -1,7 +1,6 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 
 from celery.app.events import Events
 from celery.events.snapshot import Polaroid, evcam
@@ -106,8 +105,7 @@ def setup(self):
         self.app.events = self.MockEvents()
         self.app.events.app = self.app
 
-    @mock.restore_logging()
-    def test_evcam(self):
+    def test_evcam(self, restore_logging):
         evcam(Polaroid, timer=timer, app=self.app)
         evcam(Polaroid, timer=timer, loglevel='CRITICAL', app=self.app)
         self.MockReceiver.raise_keyboard_interrupt = True
diff --git a/t/unit/fixups/test_django.py b/t/unit/fixups/test_django.py
--- a/t/unit/fixups/test_django.py
+++ b/t/unit/fixups/test_django.py
@@ -2,10 +2,10 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 
 from celery.fixups.django import (DjangoFixup, DjangoWorkerFixup,
                                   FixupWarning, _maybe_close_fd, fixup)
+from t.unit import conftest
 
 
 class FixupCase:
@@ -54,6 +54,18 @@ def test_autodiscover_tasks(self, patching):
         apps.get_app_configs.return_value = configs
         assert f.autodiscover_tasks() == [c.name for c in configs]
 
+    @pytest.mark.masked_modules('django')
+    def test_fixup_no_django(self, patching, mask_modules):
+        with patch('celery.fixups.django.DjangoFixup') as Fixup:
+            patching.setenv('DJANGO_SETTINGS_MODULE', '')
+            fixup(self.app)
+            Fixup.assert_not_called()
+
+            patching.setenv('DJANGO_SETTINGS_MODULE', 'settings')
+            with pytest.warns(FixupWarning):
+                fixup(self.app)
+            Fixup.assert_not_called()
+
     def test_fixup(self, patching):
         with patch('celery.fixups.django.DjangoFixup') as Fixup:
             patching.setenv('DJANGO_SETTINGS_MODULE', '')
@@ -61,11 +73,7 @@ def test_fixup(self, patching):
             Fixup.assert_not_called()
 
             patching.setenv('DJANGO_SETTINGS_MODULE', 'settings')
-            with mock.mask_modules('django'):
-                with pytest.warns(FixupWarning):
-                    fixup(self.app)
-                Fixup.assert_not_called()
-            with mock.module_exists('django'):
+            with conftest.module_exists('django'):
                 import django
                 django.VERSION = (1, 11, 1)
                 fixup(self.app)
@@ -257,17 +265,17 @@ def test_on_worker_ready(self):
                 f._settings.DEBUG = True
                 f.on_worker_ready()
 
-    def test_validate_models(self, patching):
-        with mock.module('django', 'django.db', 'django.core',
-                         'django.core.cache', 'django.conf',
-                         'django.db.utils'):
-            f = self.Fixup(self.app)
-            f.django_setup = Mock(name='django.setup')
-            patching.modules('django.core.checks')
-            from django.core.checks import run_checks
-            f.validate_models()
-            f.django_setup.assert_called_with()
-            run_checks.assert_called_with()
+    @pytest.mark.patched_module('django', 'django.db', 'django.core',
+                                'django.core.cache', 'django.conf',
+                                'django.db.utils')
+    def test_validate_models(self, patching, module):
+        f = self.Fixup(self.app)
+        f.django_setup = Mock(name='django.setup')
+        patching.modules('django.core.checks')
+        from django.core.checks import run_checks
+        f.validate_models()
+        f.django_setup.assert_called_with()
+        run_checks.assert_called_with()
 
     def test_django_setup(self, patching):
         patching('celery.fixups.django.symbol_by_name')
diff --git a/t/unit/security/test_certificate.py b/t/unit/security/test_certificate.py
--- a/t/unit/security/test_certificate.py
+++ b/t/unit/security/test_certificate.py
@@ -3,10 +3,10 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 
 from celery.exceptions import SecurityError
 from celery.security.certificate import Certificate, CertStore, FSCertStore
+from t.unit import conftest
 
 from . import CERT1, CERT2, KEY1
 from .case import SecurityCase
@@ -84,7 +84,7 @@ def test_init(self, Certificate, glob, isdir):
         cert.has_expired.return_value = False
         isdir.return_value = True
         glob.return_value = ['foo.cert']
-        with mock.open():
+        with conftest.open():
             cert.get_id.return_value = 1
 
             path = os.path.join('var', 'certs')
diff --git a/t/unit/security/test_security.py b/t/unit/security/test_security.py
--- a/t/unit/security/test_security.py
+++ b/t/unit/security/test_security.py
@@ -19,13 +19,13 @@
 from unittest.mock import Mock, patch
 
 import pytest
-from case import mock
 from kombu.exceptions import SerializerNotInstalled
 from kombu.serialization import disable_insecure_serializers, registry
 
 from celery.exceptions import ImproperlyConfigured, SecurityError
 from celery.security import disable_untrusted_serializers, setup_security
 from celery.security.utils import reraise_errors
+from t.unit import conftest
 
 from . import CERT1, KEY1
 from .case import SecurityCase
@@ -120,7 +120,7 @@ def effect(*args):
 
         self.app.conf.task_serializer = 'auth'
         self.app.conf.accept_content = ['auth']
-        with mock.open(side_effect=effect):
+        with conftest.open(side_effect=effect):
             with patch('celery.security.registry') as registry:
                 store = Mock()
                 self.app.setup_security(['json'], key, cert, store)
diff --git a/t/unit/tasks/test_tasks.py b/t/unit/tasks/test_tasks.py
--- a/t/unit/tasks/test_tasks.py
+++ b/t/unit/tasks/test_tasks.py
@@ -4,12 +4,12 @@
 from unittest.mock import ANY, MagicMock, Mock, patch, sentinel
 
 import pytest
-from case import ContextMock
 from kombu import Queue
 from kombu.exceptions import EncodeError
 
 from celery import Task, group, uuid
 from celery.app.task import _reprtask
+from celery.contrib.testing.mocks import ContextMock
 from celery.exceptions import Ignore, ImproperlyConfigured, Retry
 from celery.result import AsyncResult, EagerResult
 from celery.utils.time import parse_iso8601
diff --git a/t/unit/utils/test_platforms.py b/t/unit/utils/test_platforms.py
--- a/t/unit/utils/test_platforms.py
+++ b/t/unit/utils/test_platforms.py
@@ -7,7 +7,6 @@
 from unittest.mock import Mock, call, patch
 
 import pytest
-from case import mock
 
 import t.skip
 from celery import _find_option_with_arg, platforms
@@ -22,6 +21,7 @@
                               set_process_title, setgid, setgroups, setuid,
                               signals)
 from celery.utils.text import WhateverIO
+from t.unit import conftest
 
 try:
     import resource
@@ -429,7 +429,7 @@ def test_without_resource(self):
     @patch('celery.platforms.signals')
     @patch('celery.platforms.maybe_drop_privileges')
     @patch('os.geteuid')
-    @patch(mock.open_fqdn)
+    @patch('builtins.open')
     def test_default(self, open, geteuid, maybe_drop,
                      signals, pidlock):
         geteuid.return_value = 0
@@ -530,7 +530,7 @@ def test_create_pidlock(self, Pidfile):
         p = Pidfile.return_value = Mock()
         p.is_locked.return_value = True
         p.remove_if_stale.return_value = False
-        with mock.stdouts() as (_, err):
+        with conftest.stdouts() as (_, err):
             with pytest.raises(SystemExit):
                 create_pidlock('/var/pid')
             assert 'already exists' in err.getvalue()
@@ -567,14 +567,14 @@ def test_is_locked(self, exists):
         assert not p.is_locked()
 
     def test_read_pid(self):
-        with mock.open() as s:
+        with conftest.open() as s:
             s.write('1816\n')
             s.seek(0)
             p = Pidfile('/var/pid')
             assert p.read_pid() == 1816
 
     def test_read_pid_partially_written(self):
-        with mock.open() as s:
+        with conftest.open() as s:
             s.write('1816')
             s.seek(0)
             p = Pidfile('/var/pid')
@@ -584,20 +584,20 @@ def test_read_pid_partially_written(self):
     def test_read_pid_raises_ENOENT(self):
         exc = IOError()
         exc.errno = errno.ENOENT
-        with mock.open(side_effect=exc):
+        with conftest.open(side_effect=exc):
             p = Pidfile('/var/pid')
             assert p.read_pid() is None
 
     def test_read_pid_raises_IOError(self):
         exc = IOError()
         exc.errno = errno.EAGAIN
-        with mock.open(side_effect=exc):
+        with conftest.open(side_effect=exc):
             p = Pidfile('/var/pid')
             with pytest.raises(IOError):
                 p.read_pid()
 
     def test_read_pid_bogus_pidfile(self):
-        with mock.open() as s:
+        with conftest.open() as s:
             s.write('eighteensixteen\n')
             s.seek(0)
             p = Pidfile('/var/pid')
@@ -655,7 +655,7 @@ def test_remove_if_stale_process_alive(self, kill):
 
     @patch('os.kill')
     def test_remove_if_stale_process_dead(self, kill):
-        with mock.stdouts():
+        with conftest.stdouts():
             p = Pidfile('/var/pid')
             p.read_pid = Mock()
             p.read_pid.return_value = 1816
@@ -668,7 +668,7 @@ def test_remove_if_stale_process_dead(self, kill):
             p.remove.assert_called_with()
 
     def test_remove_if_stale_broken_pid(self):
-        with mock.stdouts():
+        with conftest.stdouts():
             p = Pidfile('/var/pid')
             p.read_pid = Mock()
             p.read_pid.side_effect = ValueError()
@@ -679,7 +679,7 @@ def test_remove_if_stale_broken_pid(self):
 
     @patch('os.kill')
     def test_remove_if_stale_unprivileged_user(self, kill):
-        with mock.stdouts():
+        with conftest.stdouts():
             p = Pidfile('/var/pid')
             p.read_pid = Mock()
             p.read_pid.return_value = 1817
@@ -704,7 +704,7 @@ def test_remove_if_stale_no_pidfile(self):
     @patch('os.getpid')
     @patch('os.open')
     @patch('os.fdopen')
-    @patch(mock.open_fqdn)
+    @patch('builtins.open')
     def test_write_pid(self, open_, fdopen, osopen, getpid, fsync):
         getpid.return_value = 1816
         osopen.return_value = 13
@@ -731,7 +731,7 @@ def test_write_pid(self, open_, fdopen, osopen, getpid, fsync):
     @patch('os.getpid')
     @patch('os.open')
     @patch('os.fdopen')
-    @patch(mock.open_fqdn)
+    @patch('builtins.open')
     def test_write_reread_fails(self, open_, fdopen,
                                 osopen, getpid, fsync):
         getpid.return_value = 1816
diff --git a/t/unit/utils/test_serialization.py b/t/unit/utils/test_serialization.py
--- a/t/unit/utils/test_serialization.py
+++ b/t/unit/utils/test_serialization.py
@@ -6,7 +6,6 @@
 
 import pytest
 import pytz
-from case import mock
 from kombu import Queue
 
 from celery.utils.serialization import (STRTOBOOL_DEFAULT_TABLE,
@@ -18,14 +17,14 @@
 
 class test_AAPickle:
 
-    def test_no_cpickle(self):
+    @pytest.mark.masked_modules('cPickle')
+    def test_no_cpickle(self, mask_modules):
         prev = sys.modules.pop('celery.utils.serialization', None)
         try:
-            with mock.mask_modules('cPickle'):
-                import pickle as orig_pickle
+            import pickle as orig_pickle
 
-                from celery.utils.serialization import pickle
-                assert pickle.dumps is orig_pickle.dumps
+            from celery.utils.serialization import pickle
+            assert pickle.dumps is orig_pickle.dumps
         finally:
             sys.modules['celery.utils.serialization'] = prev
 
diff --git a/t/unit/utils/test_threads.py b/t/unit/utils/test_threads.py
--- a/t/unit/utils/test_threads.py
+++ b/t/unit/utils/test_threads.py
@@ -1,10 +1,10 @@
 from unittest.mock import patch
 
 import pytest
-from case import mock
 
 from celery.utils.threads import (Local, LocalManager, _FastLocalStack,
                                   _LocalStack, bgThread)
+from t.unit import conftest
 
 
 class test_bgThread:
@@ -17,7 +17,7 @@ def body(self):
                 raise KeyError()
 
         with patch('os._exit') as _exit:
-            with mock.stdouts():
+            with conftest.stdouts():
                 _exit.side_effect = ValueError()
                 t = T()
                 with pytest.raises(ValueError):
diff --git a/t/unit/worker/test_autoscale.py b/t/unit/worker/test_autoscale.py
--- a/t/unit/worker/test_autoscale.py
+++ b/t/unit/worker/test_autoscale.py
@@ -2,7 +2,7 @@
 from time import monotonic
 from unittest.mock import Mock, patch
 
-from case import mock
+import pytest
 
 from celery.concurrency.base import BasePool
 from celery.utils.objects import Bunch
@@ -100,8 +100,8 @@ def join(self, timeout=None):
             x.stop()
         assert not x.joined
 
-    @mock.sleepdeprived(module=autoscale)
-    def test_body(self):
+    @pytest.mark.sleepdeprived_patched_module(autoscale)
+    def test_body(self, sleepdeprived):
         worker = Mock(name='worker')
         x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker)
         x.body()
@@ -216,8 +216,8 @@ def body(self):
         _exit.assert_called_with(1)
         stderr.write.assert_called()
 
-    @mock.sleepdeprived(module=autoscale)
-    def test_no_negative_scale(self):
+    @pytest.mark.sleepdeprived_patched_module(autoscale)
+    def test_no_negative_scale(self, sleepdeprived):
         total_num_processes = []
         worker = Mock(name='worker')
         x = autoscale.Autoscaler(self.pool, 10, 3, worker=worker)
diff --git a/t/unit/worker/test_consumer.py b/t/unit/worker/test_consumer.py
--- a/t/unit/worker/test_consumer.py
+++ b/t/unit/worker/test_consumer.py
@@ -5,8 +5,8 @@
 
 import pytest
 from billiard.exceptions import RestartFreqExceeded
-from case import ContextMock
 
+from celery.contrib.testing.mocks import ContextMock
 from celery.utils.collections import LimitedSet
 from celery.worker.consumer.agent import Agent
 from celery.worker.consumer.consumer import (CANCEL_TASKS_BY_DEFAULT, CLOSE,
diff --git a/t/unit/worker/test_worker.py b/t/unit/worker/test_worker.py
--- a/t/unit/worker/test_worker.py
+++ b/t/unit/worker/test_worker.py
@@ -11,7 +11,6 @@
 
 import pytest
 from amqp import ChannelError
-from case import mock
 from kombu import Connection
 from kombu.asynchronous import get_event_loop
 from kombu.common import QoS, ignore_errors
@@ -804,8 +803,8 @@ def test_with_autoscaler(self):
         assert worker.autoscaler
 
     @t.skip.if_win32
-    @mock.sleepdeprived(module=autoscale)
-    def test_with_autoscaler_file_descriptor_safety(self):
+    @pytest.mark.sleepdeprived_patched_module(autoscale)
+    def test_with_autoscaler_file_descriptor_safety(self, sleepdeprived):
         # Given: a test celery worker instance with auto scaling
         worker = self.create_worker(
             autoscale=[10, 5], use_eventloop=True,
@@ -853,8 +852,8 @@ def test_with_autoscaler_file_descriptor_safety(self):
         worker.pool.terminate()
 
     @t.skip.if_win32
-    @mock.sleepdeprived(module=autoscale)
-    def test_with_file_descriptor_safety(self):
+    @pytest.mark.sleepdeprived_patched_module(autoscale)
+    def test_with_file_descriptor_safety(self, sleepdeprived):
         # Given: a test celery worker instance
         worker = self.create_worker(
             autoscale=[10, 5], use_eventloop=True,