diff --git a/Pipfile b/Pipfile
index 123122bb5d3cdd5b0abf66ecec6906d0154a4e02..a04ff596da5df669dcfb74da4376731bf1f577d5 100644
--- a/Pipfile
+++ b/Pipfile
@@ -23,11 +23,14 @@ psycopg2-binary = "*"
 flask-restplus = "*"
 celery = {extras = ["auth", "yaml", "msgpack", "redis"]}
 python-ldap = "*"
+mockredispy = "*"
 
 [dev-packages]
 pytest-cov = "*"
 pylint = "*"
 pytest = "*"
+pytest-mock = "*"
+mock = "*"
 
 [requires]
 python_version = "3.6"
diff --git a/portal/rest/errors.py b/portal/rest/errors.py
index 3c74490983652499c9153c3592084e4cded0323f..27e6805d2e09675c3366911e3210ff9f9225d7e7 100644
--- a/portal/rest/errors.py
+++ b/portal/rest/errors.py
@@ -1,3 +1,4 @@
+import flask
 from flask import Flask
 import json
 import logging
@@ -20,7 +21,7 @@ def load_errors(app: Flask):
 
 @rest_api.errorhandler
 def default_error_handler():
-    return {'message': 'Default error handler has been triggered'}, 401
+    return flask.jsonify({'message': 'Default error handler has been triggered'}), 401
 
 
 @rest_api.errorhandler(PortalAPIError)
@@ -32,27 +33,27 @@ def handle_portal_api_error(ex: PortalAPIError):
 @rest_api.errorhandler(NoAuthorizationError)
 def handle_missing_auth_header(ex: NoAuthorizationError):
     log.debug(f"[AUTH] Auth headers are missing: {ex} ")
-    return json.dumps({'message': 'Auth headers is missing', 'error': f'{ex}'}), 401
+    return flask.jsonify({'message': 'Auth headers is missing', 'error': f'{ex}'}), 401
 
 
 @rest_api.errorhandler(IncorrectCredentialsError)
 def handle_missing_auth_header(ex: IncorrectCredentialsError):
     log.debug(f"[AUTH] Credentials are incorrect: {ex} ")
-    return json.dumps({'message': 'Credentials are incorrect', 'error': f'{ex}'}), 401
+    return flask.jsonify({'message': 'Credentials are incorrect', 'error': f'{ex}'}), 401
 
 
 @rest_api.errorhandler(ValidationError)
 def handle_validation_error(ex: ValidationError):
     log.warning(f"[VALID] Validation failed: {ex}")
-    return json.dumps({'message': f"Validation failed on: {ex.messages}"}), 400
+    return flask.jsonify({'message': f"Validation failed on: {ex.messages}"}), 400
 
 
 @rest_api.errorhandler(SQLAlchemyError)
 def handle_db_error(ex: SQLAlchemyError):
     log.error(f"[DB] Error: {ex}", ex)
-    return json.dumps({'message': f'Database error: {ex}'}), 400
+    return flask.jsonify({'message': f'Database error: {ex}'}), 400
 
 
 @rest_api.errorhandler(NotImplementedError)
 def handle_not_implemented_error():
-    return json.dumps({'message': f'Not implemented yet!'}), 404
+    return flask.jsonify({'message': f'Not implemented yet!'}), 404
diff --git a/portal/service/projects.py b/portal/service/projects.py
index a1fdb0d435d278d1035039d02a5c08ad8aba2ddb..76457033dd255ff7fae31508ac213a1af36856b8 100644
--- a/portal/service/projects.py
+++ b/portal/service/projects.py
@@ -89,7 +89,8 @@ def create_project(course: Course, data: dict) -> Project:
 
     Returns(Project): Project instance
     """
-    test_files_source = data['config']['test_files_source']
+    config = data.get('config')
+    test_files_source = config.get('test_files_source') if config else None
     new_project = Project(course=course, test_files_source=test_files_source)
     __set_project_data(project=new_project, data=data)
     log.info(f"[CREATE] Project for course {course.id} ({course.codename}): "
diff --git a/tests/rest/test_group.py b/tests/rest/test_group.py
index 9c149a8aa4e7ec21c5236ead14759e8cc0fa165e..44aada37eb84af8565db3ec82c5c024185139401 100644
--- a/tests/rest/test_group.py
+++ b/tests/rest/test_group.py
@@ -279,9 +279,9 @@ def test_remove_user_not_in_group(client):
     u = User.query.filter_by(username="student1").first()
     assert g not in u.groups
 
-    with pytest.raises(PortalAPIError):
-        path = f"/courses/{tc2.codename}/groups/{g.name}/users/{u.username}"
-        utils.make_request(client, path, method='delete')
+    path = f"/courses/{tc2.codename}/groups/{g.name}/users/{u.username}"
+    response = utils.make_request(client, path, method='delete')
+    response.status_code == 400
 
     g_updated = Group.query.filter(
         Group.course_id == tc2.id).filter(Group.id == g.id).first()
diff --git a/tests/rest/test_project.py b/tests/rest/test_project.py
index 5bce235293e6d97e6092a832be35a17bfacb6846..761eb56a7a50dbb57456f8f3cb076cd8174281f2 100644
--- a/tests/rest/test_project.py
+++ b/tests/rest/test_project.py
@@ -1,6 +1,7 @@
 import json
 from datetime import timedelta
 from flask_jwt_extended import create_access_token
+import pytest
 
 from portal.database.models import Course, Project, User
 from portal.tools.time import current_time, strip_seconds
@@ -31,8 +32,8 @@ def test_create(client):
         "name": "new_project",
         "config": {
             "test_files_source": "foo@git.git",
-        },
-    }
+            },
+        }
     request_json = json.dumps(request_dict)
     response = utils.make_request(client, f"/courses/{cpp.codename}/projects", method='post',
                                   data=request_json,
@@ -68,7 +69,7 @@ def test_update(client):
     p_name = p.name
     request_dict = dict(
         name="new project name",
-    )
+        )
     request_json = json.dumps(request_dict)
     response = utils.make_request(client, f"/courses/{cpp.codename}/projects/{p.name}",
                                   data=request_json, method='put',
@@ -120,7 +121,7 @@ def test_config_update(client):
         test_files_source="new source",
         pre_submit_script="a python script",
         submissions_allowed_to=new_time
-    )
+        )
     request_json = json.dumps(request_dict, cls=utils.DateTimeEncoder)
 
     response = utils.make_request(client, f"/courses/{cpp.codename}/projects/{p.name}/config",
@@ -185,9 +186,9 @@ def test_create_submission(client):
                 "url": "https://gitlab.fi.muni.cz/xkompis/test-hello-world.git",
                 "branch": "master",
                 "checkout": "master"
+                }
             }
         }
-    }
     request_json = json.dumps(request_dict, cls=utils.DateTimeEncoder)
 
     path = f"/courses/{cpp.codename}/projects/{p.name}/submissions"
diff --git a/tests/rest/test_role.py b/tests/rest/test_role.py
index 161265c7636b772e101f981bfa173c85f34a49b1..983e77973dad0550c7fe85155ee9e91c3ae4a198 100644
--- a/tests/rest/test_role.py
+++ b/tests/rest/test_role.py
@@ -1,9 +1,7 @@
-import pytest
+import json
 
 from portal.database.models import Course, Role, User
-from portal.service.errors import PortalAPIError
 from . import utils
-import json
 
 
 def test_list(client):
@@ -28,7 +26,7 @@ def test_create(client):
     request_dict = {
         "name": "new role",
         "description": "new role desc"
-    }
+        }
     request_json = json.dumps(request_dict)
     response = utils.make_request(client, f"/courses/{cpp.codename}/roles", data=request_json,
                                   headers={"content-type": "application/json"}, method='post')
@@ -64,9 +62,10 @@ def test_update(client):
     request_dict = dict(
         name="new role name",
         description="new role desc",
-    )
+        )
     request_json = json.dumps(request_dict)
-    response = utils.make_request(client, f"/courses/{cpp.codename}/roles/{r.name}", data=request_json,
+    response = utils.make_request(client, f"/courses/{cpp.codename}/roles/{r.name}",
+                                  data=request_json,
                                   headers={"content-type": "application/json"}, method='put')
     assert response.status_code == 204
     assert response.mimetype == 'application/json'
@@ -118,9 +117,10 @@ def test_users_update_add(client):
 
     request_dict = dict(
         add=[user.id]
-    )
+        )
     request_json = json.dumps(request_dict)
-    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users", data=request_json,
+    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users",
+                                  data=request_json,
                                   headers={"content-type": "application/json"}, method='put')
 
     assert response.status_code == 204
@@ -142,9 +142,10 @@ def test_users_update_add_duplicate(client):
 
     request_dict = dict(
         add=[user.id]
-    )
+        )
     request_json = json.dumps(request_dict)
-    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users", data=request_json,
+    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users",
+                                  data=request_json,
                                   headers={"content-type": "application/json"}, method='put')
 
     assert response.status_code == 204
@@ -166,9 +167,10 @@ def test_users_update_remove(client):
 
     request_dict = dict(
         remove=[user.id]
-    )
+        )
     request_json = json.dumps(request_dict)
-    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users", data=request_json,
+    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users",
+                                  data=request_json,
                                   headers={"content-type": "application/json"}, method='put')
 
     assert response.status_code == 204
@@ -190,9 +192,10 @@ def test_users_update_remove_user_not_in(client):
 
     request_dict = dict(
         remove=[user.id]
-    )
+        )
     request_json = json.dumps(request_dict)
-    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users", data=request_json,
+    response = utils.make_request(client, f"/courses/{c.codename}/roles/{r.name}/users",
+                                  data=request_json,
                                   headers={"content-type": "application/json"}, method='put')
 
     assert response.status_code == 204
@@ -269,9 +272,9 @@ def test_remove_user_not_in(client):
     u = User.query.filter_by(username="student1").first()
     assert r not in u.roles
 
-    with pytest.raises(PortalAPIError):
-        utils.make_request(
-            client, f"/courses/{c.codename}/roles/{r.name}/users/{u.username}", method='delete')
+    response = utils.make_request(
+        client, f"/courses/{c.codename}/roles/{r.name}/users/{u.username}", method='delete')
+    assert response.status_code == 400
 
     r_updated = Role.query.filter(
         Role.course_id == c.id).filter(Role.id == r.id).first()
@@ -301,10 +304,11 @@ def test_permissions_update(client):
         view_course_full=True,
         write_roles=True,
         read_submissions_all=True
-    )
+        )
     request_json = json.dumps(request_dict, cls=utils.DateTimeEncoder)
 
-    response = utils.make_request(client, f"/courses/{cpp.codename}/roles/{r.name}/permissions", data=request_json,
+    response = utils.make_request(client, f"/courses/{cpp.codename}/roles/{r.name}/permissions",
+                                  data=request_json,
                                   headers={"content-type": "application/json"}, method='put')
     assert response.status_code == 204
     assert response.mimetype == 'application/json'
diff --git a/tests/rest/test_user.py b/tests/rest/test_user.py
index 96d46133ff81fb8f8ab0a5e0f26625d0d3701854..6d413422d7eea610a9957efe5bc114a5121d3f0b 100644
--- a/tests/rest/test_user.py
+++ b/tests/rest/test_user.py
@@ -135,8 +135,8 @@ def test_list_filter_group(client):
 
 
 def test_list_filter_missing_course(client):
-    with pytest.raises(PortalAPIError):
-        utils.make_request(client, '/users?group=g1', method='get')
+    response = utils.make_request(client, '/users?group=g1', method='get')
+    assert response.status_code == 400
 
 
 def test_read(client):
@@ -231,10 +231,10 @@ def test_read_submissions_filter_course_project(client):
 
 
 def test_read_submissions_filter_missing_course(client):
-    with pytest.raises(PortalAPIError):
-        user = User.query.filter_by(username="student1").first()
-        path = f"/users/{user.id}/submissions?project=p1"
-        utils.make_request(client, path, method='get')
+    user = User.query.filter_by(username="student1").first()
+    path = f"/users/{user.id}/submissions?project=p1"
+    response = utils.make_request(client, path, method='get')
+    assert response.status_code == 400
 
 
 def test_read_roles(client):