diff --git a/sbin/prepare_dev_env.sh b/sbin/prepare_dev_env.sh
index 080ceb4725570870313225300b5730364c74bee4..d3dbc6094ef114ee9896a64ac23857b887a36d05 100755
--- a/sbin/prepare_dev_env.sh
+++ b/sbin/prepare_dev_env.sh
@@ -5,7 +5,7 @@
 #
 
 # Url to the jumppad download location
-jumppad_download="https://git.astron.nl/lofar2.0/tango/-/package_files/37347/download"
+jumppad_download="https://git.astron.nl/lofar2.0/tango/-/package_files/40604/download"
 
 if [ -z "$LOFAR20_DIR" ]; then
     # We assume we aren't in the PATH, so we can derive our path.
diff --git a/tangostationcontrol/integration_test/base.py b/tangostationcontrol/integration_test/base.py
index cc42e12a2cfda188697e0cf6eb9345998bb79531..c944fda682c6f48b3d38b94035d5f1a87a0e93e8 100644
--- a/tangostationcontrol/integration_test/base.py
+++ b/tangostationcontrol/integration_test/base.py
@@ -3,7 +3,6 @@
 
 import unittest
 
-import asynctest
 import testscenarios
 from tangostationcontrol.common.lofar_logging import configure_logger
 
@@ -25,7 +24,9 @@ class IntegrationTestCase(BaseIntegrationTestCase):
         super().setUp()
 
 
-class IntegrationAsyncTestCase(testscenarios.WithScenarios, asynctest.TestCase):
+class IntegrationAsyncTestCase(
+    testscenarios.WithScenarios, unittest.IsolatedAsyncioTestCase
+):
     """Integration test case base class for all asyncio unit tests."""
 
     def setUp(self):
diff --git a/tangostationcontrol/integration_test/default/client/test_opcua_client_against_server.py b/tangostationcontrol/integration_test/default/client/test_opcua_client_against_server.py
index f941298b8ca94fe4320618acba560865d8c8d844..c8bce5e602f2c3322466c04eb70740f2dd24a782 100644
--- a/tangostationcontrol/integration_test/default/client/test_opcua_client_against_server.py
+++ b/tangostationcontrol/integration_test/default/client/test_opcua_client_against_server.py
@@ -90,7 +90,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
         try:
@@ -106,7 +105,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
         try:
@@ -135,7 +133,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
         try:
@@ -166,7 +163,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
 
@@ -185,7 +181,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
         try:
@@ -208,7 +203,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
         try:
@@ -230,7 +224,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             self.namespace,
             5,
             self.fault_func,
-            self.loop,
             OPCUAConnectionStatus(),
         )
 
@@ -251,7 +244,6 @@ class TestClientServer(base.IntegrationAsyncTestCase):
             5,
             self.fault_func,
             OPCUAConnectionStatus(),
-            self.loop,
         )
 
         try:
diff --git a/tangostationcontrol/test-requirements.txt b/tangostationcontrol/test-requirements.txt
index 450da51eaace2090c33ccba0ea08fb052046d18e..cc253161b5ac00411a4a8954b7bf3e4553d91221 100644
--- a/tangostationcontrol/test-requirements.txt
+++ b/tangostationcontrol/test-requirements.txt
@@ -3,7 +3,6 @@
 # integration process, which may cause wedges in the gate later.
 
 importlib-metadata<2.0.0,>=0.12;python_version<"3.8"
-asynctest>=0.13.0 # Apache-2.0
 bandit>=1.6.0 # Apache-2.0
 virtualenv>=20.16.0 # MIT
 build>=0.8.0 # MIT
diff --git a/tangostationcontrol/test/base.py b/tangostationcontrol/test/base.py
index 8920e3bd3c68e317433d10854ba6bb7f4c6c4538..1149385f39c735cb6440a3b2031d053190ae6c63 100644
--- a/tangostationcontrol/test/base.py
+++ b/tangostationcontrol/test/base.py
@@ -7,7 +7,6 @@ from unittest import mock
 from typing import Dict
 from typing import Union
 
-import asynctest
 import testscenarios
 from tangostationcontrol.common.lofar_logging import configure_logger
 
@@ -41,7 +40,7 @@ class TestCase(BaseTestCase):
         super().setUp()
 
 
-class AsyncTestCase(testscenarios.WithScenarios, asynctest.TestCase):
+class AsyncTestCase(testscenarios.WithScenarios, unittest.IsolatedAsyncioTestCase):
     """Test case base class for all asyncio unit tests."""
 
     def setUp(self):
diff --git a/tangostationcontrol/test/clients/test_opcua_client.py b/tangostationcontrol/test/clients/test_opcua_client.py
index 01987c99e3e2bae922e9e843db9d4e95bd07085d..af9f558ac51a61435538e547e692dab4a256e5a4 100644
--- a/tangostationcontrol/test/clients/test_opcua_client.py
+++ b/tangostationcontrol/test/clients/test_opcua_client.py
@@ -3,9 +3,10 @@
 
 import asyncio
 import io
+import unittest
 from unittest import mock
+from unittest.mock import patch
 
-import asynctest
 import asyncua
 import numpy
 
@@ -15,8 +16,6 @@ from tangostationcontrol.clients.opcua_client import (
     OPCUAConnectionStatus,
 )
 
-from test import base
-
 
 class AttrProps:
     def __init__(self, numpy_type):
@@ -44,27 +43,39 @@ IMAGE_SHAPE = (2, 3)
 DIMENSION_TESTS = [SCALAR_SHAPE, SPECTRUM_SHAPE, IMAGE_SHAPE]
 
 
-class TestOPCua(base.AsyncTestCase):
-    @asynctest.patch.object(OPCUAConnection, "ping")
-    @asynctest.patch.object(OPCUAConnection, "_servername")
-    @asynctest.patch.object(opcua_client, "Client")
+def create_mocked_coroutine(return_value=None):
+    if return_value is None:
+        return_value = mock.Mock()
+
+    async def mock_coro(*args, **kwargs):
+        return return_value
+
+    return mock.Mock(wraps=mock_coro)
+
+
+class TestOPCua(unittest.IsolatedAsyncioTestCase):
+    @patch.object(OPCUAConnection, "ping")
+    @patch.object(OPCUAConnection, "_servername")
+    @patch.object(opcua_client, "Client")
     async def test_opcua_connection(self, m_opc_client, m_servername, m_ping):
         """
         This tests verifies whether the correct connection steps happen. It checks whether we can init an OPCUAConnection object
         Whether we can set the namespace, and the OPCua client.
         """
 
-        m_opc_client_members = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.get_namespace_index = asynctest.asynctest.CoroutineMock(
+        m_opc_client_members = create_mocked_coroutine()
+        m_opc_client_members.get_namespace_index = create_mocked_coroutine(
             return_value=42
         )
-        m_opc_client_members.connect = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.disconnect = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.send_hello = asynctest.asynctest.CoroutineMock()
-
-        m_opc_client_members.update_protocol_attributes = (
-            asynctest.asynctest.CoroutineMock()
-        )
+        m_opc_client_members.connect = create_mocked_coroutine()
+        m_opc_client_members.disconnect = create_mocked_coroutine()
+        m_opc_client_members.send_hello = create_mocked_coroutine()
+
+        m_objects_node = mock.Mock()
+        m_objects_node.get_child = create_mocked_coroutine()
+        m_objects_node.get_children_descriptions = create_mocked_coroutine([])
+        m_opc_client_members.get_objects_node = mock.Mock(return_value=m_objects_node)
+        m_opc_client_members.update_protocol_attributes = create_mocked_coroutine()
         m_opc_client.return_value = m_opc_client_members
 
         test_client = OPCUAConnection(
@@ -73,7 +84,6 @@ class TestOPCua(base.AsyncTestCase):
             5,
             mock.Mock(),
             OPCUAConnectionStatus(),
-            self.loop,
         )
 
         try:
@@ -89,10 +99,10 @@ class TestOPCua(base.AsyncTestCase):
         finally:
             await test_client.stop()
 
-    @asynctest.patch.object(OPCUAConnection, "ping")
-    @asynctest.patch.object(OPCUAConnection, "_servername")
-    @asynctest.patch.object(opcua_client, "Client")
-    @asynctest.patch.object(opcua_client, "ProtocolAttribute")
+    @patch.object(OPCUAConnection, "ping")
+    @patch.object(OPCUAConnection, "_servername")
+    @patch.object(opcua_client, "Client")
+    @patch.object(opcua_client, "ProtocolAttribute")
     async def test_opcua_attr_setup(
         self, m_protocol_attr, m_opc_client, m_servername, m_ping
     ):
@@ -104,22 +114,18 @@ class TestOPCua(base.AsyncTestCase):
         Test succeeds if there are no errors.
         """
 
-        m_opc_client_members = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.get_namespace_index = asynctest.asynctest.CoroutineMock(
+        m_opc_client_members = create_mocked_coroutine()
+        m_opc_client_members.get_namespace_index = create_mocked_coroutine(
             return_value=2
         )
-        m_opc_client_members.connect = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.disconnect = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.send_hello = asynctest.asynctest.CoroutineMock()
-        m_objects_node = asynctest.Mock()
-        m_objects_node.get_child = asynctest.asynctest.CoroutineMock()
-        m_objects_node.get_children_descriptions = asynctest.asynctest.CoroutineMock()
-        m_opc_client_members.get_objects_node = asynctest.Mock(
-            return_value=m_objects_node
-        )
-        m_opc_client_members.update_protocol_attributes = (
-            asynctest.asynctest.CoroutineMock()
-        )
+        m_opc_client_members.connect = create_mocked_coroutine()
+        m_opc_client_members.disconnect = create_mocked_coroutine()
+        m_opc_client_members.send_hello = create_mocked_coroutine()
+        m_objects_node = mock.Mock()
+        m_objects_node.get_child = create_mocked_coroutine()
+        m_objects_node.get_children_descriptions = create_mocked_coroutine([])
+        m_opc_client_members.get_objects_node = mock.Mock(return_value=m_objects_node)
+        m_opc_client_members.update_protocol_attributes = create_mocked_coroutine()
 
         m_opc_client.return_value = m_opc_client_members
 
@@ -153,7 +159,6 @@ class TestOPCua(base.AsyncTestCase):
                     5,
                     mock.Mock(),
                     OPCUAConnectionStatus(),
-                    self.loop,
                 )
 
                 try:
@@ -240,7 +245,7 @@ class TestOPCua(base.AsyncTestCase):
             for i in ATTR_TEST_TYPES:
                 self._get_test_value(j, i.numpy_type)
 
-                m_node = asynctest.asynctest.CoroutineMock()
+                m_node = mock.Mock()
 
                 if len(j) == 1:
                     test = opcua_client.ProtocolAttribute(
@@ -274,7 +279,7 @@ class TestOPCua(base.AsyncTestCase):
 
         # test 0-2 dimensions of strings
         for dims in range(0, 2):
-            m_node = asynctest.asynctest.CoroutineMock()
+            m_node = mock.Mock()
             m_node.get_value.return_value = get_unicode_value(dims)
 
             # create the ProtocolAttribute to test
@@ -372,7 +377,7 @@ class TestOPCua(base.AsyncTestCase):
                     ),
                 )
 
-        m_node = asynctest.asynctest.CoroutineMock()
+        m_node = mock.Mock()
         m_node.set_data_value.return_value = asyncio.Future()
         m_node.set_data_value.return_value.set_result(None)
 
diff --git a/tangostationcontrol/tox.ini b/tangostationcontrol/tox.ini
index 3e4f13eb407b5df5a4724ea4c7fa27cc83ace5db..499efc4f571bfa6e6626dda90a79c1724afe4d8a 100644
--- a/tangostationcontrol/tox.ini
+++ b/tangostationcontrol/tox.ini
@@ -2,7 +2,7 @@
 min_version = 4.3.3
 requires =
     tox-ignore-env-name-mismatch ~= 0.2.0
-envlist = black,pep8,pylint,py310,docs
+envlist = black,pep8,pylint,py3{10,11},docs
 
 [testenv]
 usedevelop = True
@@ -10,8 +10,6 @@ package = wheel
 wheel_build_env = .pkg
 ; Python and tox variables are used to access modules and binaries instead of
 ; directly. This makes the setup robust for using sitepackages=True.
-install_command = {envbindir}/pip3 install {opts} {packages}
-passenv = HOME
 setenv =
    PYTHONWARNINGS=default::DeprecationWarning
 ; Share the same envdir with as many jobs as possible due to extensive time it
@@ -24,17 +22,12 @@ deps =
 allowlist_externals =
     {work_dir}/.tox/bin/python
 commands_pre =
-    {work_dir}/.tox/bin/python -m tox --version
     {envpython} --version
+    {work_dir}/.tox/bin/python -m tox --version
 commands =
     {envpython} -m pytest --version
     {envpython} -m pytest -v --log-level=DEBUG --forked test/{posargs}
 
-; We can't detect the current Python version for an environment dynamically
-; so each Python version specific job needs its own envdir.
-[testenv:py310]
-envdir = {toxworkdir}/testenvpy310
-
 [testenv:integration]
 allowlist_externals =
     {work_dir}/.tox/bin/python