diff --git a/src/postorius/tests/__init__.py b/src/postorius/tests/__init__.py
index 9999672..3153660 100644
--- a/src/postorius/tests/__init__.py
+++ b/src/postorius/tests/__init__.py
@@ -15,10 +15,14 @@
 # You should have received a copy of the GNU General Public License along with
 # Postorius.  If not, see <http://www.gnu.org/licenses/>.
 
+import vcr
+
+from django.conf import settings
+
 from postorius.tests import test_utils
 
-__test__ = {
-    "Test Utils": test_utils,
-    # "Page Tests": test_pages,
-    # "Doctest": tests,
-}
+
+MM_VCR = vcr.VCR(serializer='json',
+                 cassette_library_dir='fixtures/vcr_cassettes',
+                 record_mode=getattr(settings, 'VCR_RECORD_MODE', 'none'),
+                 match_on=['uri', 'method', 'body'])
diff --git a/src/postorius/tests/mailman_api_tests/__init__.py b/src/postorius/tests/mailman_api_tests/__init__.py
index c4d5c4e..630f8d9 100644
--- a/src/postorius/tests/mailman_api_tests/__init__.py
+++ b/src/postorius/tests/mailman_api_tests/__init__.py
@@ -14,34 +14,3 @@
 #
 # You should have received a copy of the GNU General Public License along with
 # Postorius.  If not, see <http://www.gnu.org/licenses/>.
-
-from mailmanclient.tests.utils import FakeMailmanClient
-
-from mock import patch
-from django.test import TestCase
-
-
-def setup_module():
-    FakeMailmanClient.setUp()
-
-def teardown_module():
-    FakeMailmanClient.tearDown()
-
-
-class MMTestCase(TestCase):
-
-    def _pre_setup(self):
-        super(MMTestCase, self)._pre_setup()
-        self.mm_client = FakeMailmanClient(
-            'http://localhost:8001/3.0', "restadmin", "restpass")
-        self.mm_client_patcher = patch('postorius.utils.Client', lambda *a, **kw: self.mm_client)
-        self.mm_client_patcher.start()
-        self.mm_client.create_domain(
-            'example.com',
-            contact_address='postmaster@example.com',
-            base_url='lists.example.com')
-
-    def _post_teardown(self):
-        self.mm_client_patcher.stop()
-        self.mm_client.delete_domain('example.com')
-        super(MMTestCase, self)._post_teardown()
diff --git a/src/postorius/tests/mailman_api_tests/test_list_index.py b/src/postorius/tests/mailman_api_tests/test_list_index.py
index 122e5a3..d72cf17 100644
--- a/src/postorius/tests/mailman_api_tests/test_list_index.py
+++ b/src/postorius/tests/mailman_api_tests/test_list_index.py
@@ -17,24 +17,43 @@
 
 import logging
 
+from django.conf import settings
 from django.core.urlresolvers import reverse
+from django.test import Client, SimpleTestCase
+from django.test.utils import override_settings
+from urllib2 import HTTPError
 
-from postorius.tests.mailman_api_tests import MMTestCase
+from postorius.utils import get_client
+from postorius.tests import MM_VCR
 
 
 logger = logging.getLogger(__name__)
 
 
-class ListIndexPageTest(MMTestCase):
+API_CREDENTIALS = {'MAILMAN_API_URL': 'http://localhost:9001',
+                   'MAILMAN_USER': 'restadmin',
+                   'MAILMAN_PASS': 'restpass'}
+
+
+@override_settings(**API_CREDENTIALS)
+class ListIndexPageTest(SimpleTestCase):
     """Tests for the list index page."""
 
+    @MM_VCR.use_cassette('test_list_index.yaml')
     def setUp(self):
-        domain = self.mm_client.get_domain('example.com')
-        self.foo_list = domain.create_list('foo')
+        self.client = Client()
+        try:
+            self.domain = get_client().create_domain('example.com')
+        except HTTPError:
+            self.domain = get_client().get_domain('example.com')
+        self.foo_list = self.domain.create_list('foo')
 
+    @MM_VCR.use_cassette('test_list_index.yaml')
     def tearDown(self):
-        self.foo_list.delete()
+        for mlist in get_client().lists:
+            mlist.delete()
 
+    @MM_VCR.use_cassette('test_list_index.yaml')
     def test_list_index_contains_one_list(self):
         # The list index page should contain the
         response = self.client.get(reverse('list_index'))
diff --git a/src/postorius/tests/mailman_api_tests/test_list_members.py b/src/postorius/tests/mailman_api_tests/test_list_members.py
index 914109c..f63223d 100644
--- a/src/postorius/tests/mailman_api_tests/test_list_members.py
+++ b/src/postorius/tests/mailman_api_tests/test_list_members.py
@@ -18,22 +18,36 @@
 
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
+from django.test import Client, SimpleTestCase
+from django.test.utils import override_settings
+from urllib2 import HTTPError
 
-from postorius.tests.mailman_api_tests import MMTestCase
+from postorius.tests import MM_VCR
+from postorius.utils import get_client
 
 
 logger = logging.getLogger(__name__)
 
 
-class ListMembersPageTest(MMTestCase):
+API_CREDENTIALS = {'MAILMAN_API_URL': 'http://localhost:9001',
+                   'MAILMAN_USER': 'restadmin',
+                   'MAILMAN_PASS': 'restpass'}
+
+
+@override_settings(**API_CREDENTIALS)
+class ListMembersPageTest(SimpleTestCase):
     """Tests for the list members page.
 
     Tests permissions and creation of list owners and moderators.
     """
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def setUp(self):
-        domain = self.mm_client.get_domain('example.com')
-        self.foo_list = domain.create_list('foo')
+        try:
+            self.domain = get_client().create_domain('example.com')
+        except HTTPError:
+            self.domain = get_client().get_domain('example.com')
+        self.foo_list = self.domain.create_list('foo')
         self.user = User.objects.create_user('testuser', 'test@example.com',
                                              'testpass')
         self.superuser = User.objects.create_superuser('testsu',
@@ -47,42 +61,50 @@
         self.foo_list.add_owner('owner@example.com')
         self.foo_list.add_moderator('moderator@example.com')
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def tearDown(self):
-        self.foo_list.delete()
+        for mlist in get_client().lists:
+            mlist.delete()
         self.user.delete()
         self.superuser.delete()
         self.owner.delete()
         self.moderator.delete()
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_page_not_accessible_if_not_logged_in(self):
         response = self.client.get(reverse('list_members',
                                            args=('foo@example.com', )))
         self.assertEqual(response.status_code, 403)
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_page_not_accessible_for_unprivileged_users(self):
         self.client.login(username='testuser', password='testpass')
         response = self.client.get(reverse('list_members',
                                            args=('foo@example.com', )))
         self.assertEqual(response.status_code, 403)
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_page_not_accessible_for_moderator(self):
         self.client.login(username='testmoderator', password='testpass')
         response = self.client.get(reverse('list_members',
                                            args=('foo@example.com', )))
         self.assertEqual(response.status_code, 403)
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_page_accessible_for_superuser(self):
         self.client.login(username='testsu', password='testpass')
         response = self.client.get(reverse('list_members',
                                            args=('foo@example.com', )))
         self.assertEqual(response.status_code, 200)
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_page_accessible_for_owner(self):
         self.client.login(username='testowner', password='testpass')
         response = self.client.get(reverse('list_members',
                                            args=('foo@example.com', )))
         self.assertEqual(response.status_code, 200)
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_add_owner(self):
         self.client.login(username='testsu', password='testpass')
         self.client.post(reverse('list_members',
@@ -90,6 +112,7 @@
                          {'owner_email': 'newowner@example.com'})
         self.assertTrue(u'newowner@example.com' in self.foo_list.owners)
 
+    @MM_VCR.use_cassette('test_list_members.yaml')
     def test_add_moderator(self):
         self.client.login(username='testsu', password='testpass')
         self.client.post(reverse('list_members',
diff --git a/src/postorius/tests/mailman_api_tests/test_list_new.py b/src/postorius/tests/mailman_api_tests/test_list_new.py
index 187c232..6f24f6b 100644
--- a/src/postorius/tests/mailman_api_tests/test_list_new.py
+++ b/src/postorius/tests/mailman_api_tests/test_list_new.py
@@ -19,24 +19,42 @@
 
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
+from django.test import SimpleTestCase
+from django.test.utils import override_settings
+from urllib2 import HTTPError
 
-from postorius.tests.mailman_api_tests import MMTestCase
+from postorius.utils import get_client
+from postorius.tests import MM_VCR
 
 
 logger = logging.getLogger(__name__)
 
 
-class ListCreationTest(MMTestCase):
+API_CREDENTIALS = {'MAILMAN_API_URL': 'http://localhost:9001',
+                   'MAILMAN_USER': 'restadmin',
+                   'MAILMAN_PASS': 'restpass'}
+
+
+@override_settings(**API_CREDENTIALS)
+class ListCreationTest(SimpleTestCase):
     """Tests for the new list page."""
 
+    @MM_VCR.use_cassette('test_list_new.yaml')
     def setUp(self):
         self.user = User.objects.create_user('user', 'user@example.com', 'pwd')
         self.superuser = User.objects.create_superuser('su', 'su@example.com',
                                                        'pwd')
+        try:
+            self.domain = get_client().create_domain('example.com')
+        except HTTPError:
+            self.domain = get_client().get_domain('example.com')
 
+    @MM_VCR.use_cassette('test_list_new.yaml')
     def tearDown(self):
         self.user.delete()
         self.superuser.delete()
+        for mlist in get_client().lists:
+            mlist.delete()
 
     def test_permission_denied(self):
         self.client.login(username='user', password='pwd')
@@ -45,7 +63,8 @@
             response,
             '/postorius/accounts/login/?next=/postorius/lists/new/')
 
-    def test_new_list_created(self):
+    @MM_VCR.use_cassette('test_list_new.yaml')
+    def test_new_list_created_with_owner(self):
         self.client.login(username='su', password='pwd')
         post_data = {'listname': 'a_new_list',
                      'mail_host': 'example.com',
@@ -53,6 +72,6 @@
                      'advertised': 'True',
                      'description': 'A new list.'}
         self.client.post(reverse('list_new'), post_data)
-        a_new_list = self.mm_client.get_list('a_new_list@example.com')
+        a_new_list = get_client().get_list('a_new_list@example.com')
         self.assertEqual(a_new_list.fqdn_listname, u'a_new_list@example.com')
         self.assertEqual(a_new_list.owners, [u'owner@example.com'])
diff --git a/src/postorius/tests/mailman_api_tests/test_list_summary.py b/src/postorius/tests/mailman_api_tests/test_list_summary.py
index 85212bf..1c01277 100644
--- a/src/postorius/tests/mailman_api_tests/test_list_summary.py
+++ b/src/postorius/tests/mailman_api_tests/test_list_summary.py
@@ -18,27 +18,45 @@
 
 from django.contrib.auth.models import User
 from django.core.urlresolvers import reverse
+from django.test import Client, SimpleTestCase
+from django.test.utils import override_settings
+from urllib2 import HTTPError
 
-from postorius.tests.mailman_api_tests import MMTestCase
+from postorius.utils import get_client
+from postorius.tests import MM_VCR
 
 
 logger = logging.getLogger(__name__)
 
 
-class ListSummaryPageTest(MMTestCase):
+API_CREDENTIALS = {'MAILMAN_API_URL': 'http://localhost:9001',
+                   'MAILMAN_USER': 'restadmin',
+                   'MAILMAN_PASS': 'restpass'}
+
+
+@override_settings(**API_CREDENTIALS)
+class ListSummaryPageTest(SimpleTestCase):
     """Tests for the list summary page.
 
     Tests accessiblity and existince of the submit form depending on
     login status.
     """
 
+    @MM_VCR.use_cassette('test_list_summary.yaml')
     def setUp(self):
-        domain = self.mm_client.get_domain('example.com')
+        self.client = Client()
+        try:
+            domain = get_client().create_domain('example.com')
+        except HTTPError:
+            domain = get_client().get_domain('example.com')
         self.foo_list = domain.create_list('foo')
 
+    @MM_VCR.use_cassette('test_list_summary.yaml')
     def tearDown(self):
-        self.foo_list.delete()
+        for mlist in get_client().lists:
+            mlist.delete()
 
+    @MM_VCR.use_cassette('test_list_summary.yaml')
     def test_list_summary_logged_out(self):
         # Response must contain list obj but not the form.
         response = self.client.get(reverse('list_summary',
@@ -49,6 +67,7 @@
         self.assertTrue('<h1>' in response.content)
         self.assertTrue('<form ' not in response.content)
 
+    @MM_VCR.use_cassette('test_list_summary.yaml')
     def test_list_summary_logged_in(self):
         # Response must contain list obj and the form.
         User.objects.create_user('testuser', 'test@example.com', 'testpass')
diff --git a/test_requirements.txt b/test_requirements.txt
new file mode 100644
index 0000000..18081eb
--- /dev/null
+++ b/test_requirements.txt
@@ -0,0 +1,4 @@
+mock
+django-nose
+coverage
+vcrpy