diff --git a/.gitignore b/.gitignore
index 49269ac6b0defe892ecad860cb66f8464eeb6b25..412a38302dfb2371890aa52dfc9151508ade353a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 builddir
 .flatpak-builder
+__pycache__
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 41c9760af48072bc43da35fc1e0d91f6f9dcb219..a69bd5f9801adcb5a571404db6c4c2e0cf7ff205 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,7 +1,20 @@
-test:lints:
+test:pycodestyle:
     image: debian:stretch
     script:
         - apt update && apt install --no-install-recommends -y gir1.2-gtk-3.0 python3-gi python3-pip python3-setuptools
         - pip3 install -r requirements-dev.txt
         - tools/tests/test-pycodestyle.sh
+
+test:pylint:
+    image: debian:stretch
+    script:
+        - apt update && apt install --no-install-recommends -y gir1.2-gtk-3.0 python3-gi python3-pip python3-setuptools
+        - pip3 install -r requirements-dev.txt
         - tools/tests/test-pylint.sh
+
+test:pytest:
+    image: debian:stretch
+    script:
+        - apt update && apt install --no-install-recommends -y gir1.2-gtk-3.0 python3-gi python3-pip python3-setuptools
+        - pip3 install -r requirements-dev.txt
+        - tools/tests/test-pytest.sh
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 1180199fc97816d86b8a07c68e54c2d13a41ebf9..6d982798067869e58933f0f4162bc92d429dbe34 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -1,3 +1,5 @@
 -r requirements.txt
 pycodestyle>=2.5.0
 pylint>=2.3.1
+pytest>=4.6.2
+requests_mock>=1.6.0
diff --git a/tests/briar/api/models/test_contacts.py b/tests/briar/api/models/test_contacts.py
new file mode 100644
index 0000000000000000000000000000000000000000..92e50f6e25228d3e7365e6c7e97cda9e4276d36d
--- /dev/null
+++ b/tests/briar/api/models/test_contacts.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2019 Nico Alt
+# SPDX-License-Identifier: AGPL-3.0-only
+# License-Filename: LICENSE.md
+
+import json
+import requests_mock
+from unittest import mock, TestCase
+
+from briar.api.models.contacts import Contacts
+
+
+class TestContacts(TestCase):
+
+    @requests_mock.Mocker()
+    def test_get(self, requests_mock):
+        api = mock.Mock()
+        contacts = Contacts(api)
+        response_mock = {}
+        response_mock["author"] = {}
+        response_mock["author"]["formatVersion"] = 1
+        response_mock["author"]["id"] = "y1wkIzAimAbYoCGgWxkWlr6vnq1F8t1QRA/UMPgI0E0="
+        response_mock["author"]["name"] = "Test"
+        response_mock["author"]["publicKey"] = "BDu6h1S02bF4W6rgoZfZ6BMjTj/9S9hNN7EQoV05qUo="
+        response_mock["contactId"] = 1
+        response_mock["alias"] = "A local nickname"
+        response_mock["handshakePublicKey"] = "XnYRd7a7E4CTqgAvh4hCxh/YZ0EPscxknB9ZcEOpSzY="
+        response_mock["verified"] = True
+
+        requests_mock.get("http://localhost:7000/v1/contacts", text=json.dumps(response_mock))
+        self.assertEqual(contacts.get(), response_mock)
diff --git a/tools/run-tests.sh b/tools/run-tests.sh
index 38df2367c527906a36e5187c7a2202a4721d0503..1d09c55e800ff107d998a5be07d058569e3962ae 100755
--- a/tools/run-tests.sh
+++ b/tools/run-tests.sh
@@ -2,3 +2,4 @@
 
 tools/tests/test-pycodestyle.sh
 tools/tests/test-pylint.sh
+tools/tests/test-pytest.sh
diff --git a/tools/tests/test-pytest.sh b/tools/tests/test-pytest.sh
new file mode 100755
index 0000000000000000000000000000000000000000..274c7b821d8347ba770db97c226d6d4134a3f019
--- /dev/null
+++ b/tools/tests/test-pytest.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+PYTHONPATH=src pytest tests/