diff --git a/test/conftest.py b/test/conftest.py
index 638a3f21f18cc1dfe4494fc5769037196aebc66f..0b14c3ddd8a43213019683b757cc896932b7bb24 100644
--- a/test/conftest.py
+++ b/test/conftest.py
@@ -57,6 +57,19 @@ def mocked_user(app, test_survey_data, mocker):
         yield user
 
 
+@pytest.fixture
+def mocked_observer_user(app, test_survey_data, mocker):
+    with app.app_context():
+        user = User(email='observer123@email.local', fullname='observerfullname',
+                    oidc_sub='fakesub', roles=ROLES.observer)
+
+        db.session.add(user)
+
+        def user_loader(*args):
+            return user
+        mocker.patch('flask_login.utils._get_user', user_loader)
+
+
 @pytest.fixture
 def test_budget_data(app):
     with app.app_context():
diff --git a/test/test_response.py b/test/test_response.py
index a6db8da695e750b9013fed02bc2727fb403da009..572d074159f5204a4aee5caae83cceaad19aef15 100644
--- a/test/test_response.py
+++ b/test/test_response.py
@@ -158,3 +158,33 @@ def test_response_route_lock_prevents_other_edits(app, mocker, client, test_surv
     assert rv.status_code == 403
     result = json.loads(rv.data.decode('utf-8'))
     assert result.get('message') == 'This survey is already locked.'
+
+
+def test_response_routes_observer(app, client, test_survey_data, mocked_observer_user):
+    # observers should not be able to modify surveys, but should be able to view all of them
+
+    rv = client.get(
+        '/api/survey/list',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 200
+
+    surveys = json.loads(rv.data.decode('utf-8'))
+    assert surveys
+
+    # load the first survey and check that the observer can view it
+    rv = client.get(
+        f'/api/response/load/{surveys[0]["year"]}/nren1',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 200
+
+    # try to lock the first survey and check that the observer can't
+    rv = client.post(
+        f'/api/response/lock/{surveys[0]["year"]}/nren1',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 403
+
+    # try to save the first survey and check that the observer can't
+    rv = client.post(
+        f'/api/response/save/{surveys[0]["year"]}/nren1',
+        headers={'Accept': ['application/json']})
+    assert rv.status_code == 403