diff --git a/lib/classes/JsonApi/Errors/ErrorHandler.php b/lib/classes/JsonApi/Errors/ErrorHandler.php
index 418065bcedd58fbc8a515e2ea48011971b2cbcba..d8e6747a63176d8f36ef0b0ace433a3ff042d1b0 100644
--- a/lib/classes/JsonApi/Errors/ErrorHandler.php
+++ b/lib/classes/JsonApi/Errors/ErrorHandler.php
@@ -14,12 +14,8 @@ use Throwable;
 
 class ErrorHandler
 {
-    /** @var \Slim\App */
-    private $app;
-
-    public function __construct(App $app)
+    public function __construct(protected App $app)
     {
-        $this->app = $app;
     }
 
     public function __invoke(
@@ -40,7 +36,7 @@ class ErrorHandler
 
         $code = $this->determineStatusCode($exception, $request->getMethod());
 
-        if ($code >= 500) {
+        if ($code >= 500 && $logErrors) {
             error_log($exception);
         }
 
diff --git a/tests/_support/Helper/Jsonapi.php b/tests/_support/Helper/Jsonapi.php
index cbb2216ed2344d37384725e8d164756de2d79d47..e754cc4fee2ee8834c5f3c6b8ee1a0b249ce8da2 100644
--- a/tests/_support/Helper/Jsonapi.php
+++ b/tests/_support/Helper/Jsonapi.php
@@ -3,11 +3,15 @@
 namespace Helper;
 
 use DI\ContainerBuilder;
+use JsonApi\Errors\ErrorHandler;
 use JsonApi\Errors\JsonApiErrorRenderer;
 use JsonApi\Middlewares\Authentication;
 use Nyholm\Psr7\Factory\Psr17Factory;
+use Psr\Container\ContainerInterface;
 use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseFactoryInterface;
 use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
 use Slim\Factory\AppFactory;
 use Slim\Interfaces\ErrorHandlerInterface;
 use WoohooLabs\Yang\JsonApi\Request\JsonApiRequestBuilder;
@@ -16,6 +20,11 @@ use WoohooLabs\Yang\JsonApi\Response\JsonApiResponse;
 // here you can define custom actions
 // all public methods declared in helper class will be available in $I
 
+/**
+ * @SuppressWarnings(PHPMD.MissingImport)
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
 class Jsonapi extends \Codeception\Module
 {
     /**
@@ -23,8 +32,6 @@ class Jsonapi extends \Codeception\Module
      * @param callable $function
      *
      * @return mixed
-     *
-     * @SuppressWarnings(PHPMD.Superglobals)
      */
     public function withPHPLib($credentials, $function)
     {
@@ -43,6 +50,99 @@ class Jsonapi extends \Codeception\Module
         return $result;
     }
 
+    /**
+     * @param string $route the name of the invocable JSONAPI route class
+     * @param array $credentials the credentials for this request
+     * @param array $args additional arguments usually from the URL
+     * @param callable(JsonApiRequestBuilder): void $callback callback to customize the request that will be send to the
+     *                                                        route
+     */
+    public function callJsonApi(string $route, array $credentials, array $args = [], $callback = null): JsonApiResponse
+    {
+        $container = $this->getContainer();
+        $request = $container
+            ->get(\Psr\Http\Message\ServerRequestFactoryInterface::class)
+            ->createServerRequest('GET', '');
+        $requestBuilder = new JsonApiRequestBuilder($request);
+        $requestBuilder->setProtocolVersion('1.0')->setHeader('Accept-Charset', 'utf-8');
+
+        // customize request
+        if (is_callable($callback)) {
+            $callback($requestBuilder);
+        }
+
+        $request = $this->provideUser($requestBuilder->getRequest(), \User::find($credentials['id']));
+
+        // copy query string to query params
+        $queryParams = [];
+        parse_str($request->getUri()->getQuery(), $queryParams);
+        $request = $request->withQueryParams($queryParams);
+
+        $container->set('request', $request);
+
+        $response = $container->get(ResponseFactoryInterface::class)->createResponse();
+        $routeHandler = $container->get($route);
+
+        try {
+            $response = $routeHandler($request, $response, $args);
+        } catch (\Exception $exception) {
+            $response = $this->handleError($container, $request, $exception);
+        }
+
+        return new JsonApiResponse($response);
+    }
+
+    /**
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    private function handleError(
+        ContainerInterface $container,
+        ServerRequestInterface $request,
+        \Throwable $exception
+    ): ResponseInterface {
+        $app = new \Slim\App($container->get(ResponseFactoryInterface::class), $container);
+        $errorHandler = new class ($app) extends ErrorHandler {
+            public function __invoke(
+                ServerRequestInterface $request,
+                \Throwable $exception,
+                bool $displayErrorDetails = false,
+                bool $logErrors = false,
+                bool $logErrorDetails = false,
+                ?\Psr\Log\LoggerInterface $logger = null
+            ): ResponseInterface {
+                $response = $this->app->getResponseFactory()->createResponse();
+                $response = $response->withHeader('Content-Type', 'application/json');
+                $response->getBody()->write($this->determinePayload($exception, false));
+
+                $code = $this->determineStatusCode($exception, $request->getMethod());
+
+                return $response->withStatus($code);
+            }
+        };
+        return $errorHandler($request, $exception);
+    }
+
+    private function provideUser(ServerRequestInterface $request, \User $user): ServerRequestInterface
+    {
+        if (!isset($GLOBALS['user']) || 'nobody' === $GLOBALS['user']->id) {
+            $GLOBALS['user'] = new \Seminar_User($user);
+            $GLOBALS['auth'] = new \Seminar_Auth();
+            $GLOBALS['auth']->auth = [
+                'uid' => $user->id,
+                'uname' => $user->username,
+                'perm' => $user->perms,
+            ];
+            $GLOBALS['perm'] = new \Seminar_Perm();
+            $GLOBALS['MAIL_VALIDATE_BOX'] = false;
+            if (isset($GLOBALS['sess'])) {
+                $GLOBALS['sess']->delete();
+            }
+            setTempLanguage($user->id);
+        }
+
+        return $request->withAttribute(\JsonApi\Middlewares\Authentication::USER_KEY, $user);
+    }
+
     /**
      * @param array    $credentials
      * @param string   $method
@@ -141,9 +241,10 @@ class Jsonapi extends \Codeception\Module
                     $y = new \Seminar_User($user->id);
                     $x = $y->getAuthenticatedUser();
 
-
                     $dbManager = \DBManager::get();
-                    $stmt = $dbManager->prepare("SELECT * FROM auth_user_md5 LEFT JOIN user_info USING (user_id) WHERE user_id = ?");
+                    $stmt = $dbManager->prepare(
+                        'SELECT * FROM auth_user_md5 LEFT JOIN user_info USING (user_id) WHERE user_id = ?'
+                    );
                     $stmt->execute([$user->id]);
 
                     return $handler->handle($request);
@@ -156,20 +257,7 @@ class Jsonapi extends \Codeception\Module
 
     private function appFactory(): \Slim\App
     {
-        $containerBuilder = new ContainerBuilder();
-
-        $containerBuilder->addDefinitions('lib/bootstrap-definitions.php');
-
-        $settings = require 'lib/classes/JsonApi/settings.php';
-        $settings($containerBuilder);
-
-        $dependencies = require 'lib/classes/JsonApi/dependencies.php';
-        $dependencies($containerBuilder);
-
-        // Build PHP_DI Container
-        $container = $containerBuilder->build();
-
-        // Instantiate the app
+        $container = $this->getContainer();
         AppFactory::setContainer($container);
         $app = AppFactory::create();
         $container->set(\Slim\App::class, $app);
@@ -185,6 +273,27 @@ class Jsonapi extends \Codeception\Module
         return $app;
     }
 
+    public function getContainerBuilder(): ContainerBuilder
+    {
+        $containerBuilder = new ContainerBuilder();
+
+        $containerBuilder->addDefinitions('lib/bootstrap-definitions.php');
+
+        $settings = require 'lib/classes/JsonApi/settings.php';
+        $settings($containerBuilder);
+
+        $dependencies = require 'lib/classes/JsonApi/dependencies.php';
+        $dependencies($containerBuilder);
+
+        return $containerBuilder;
+    }
+
+    public function getContainer(): ContainerInterface
+    {
+        $builder = $this->getContainerBuilder();
+        return $builder->build();
+    }
+
     public function storeJsonMD(
         string $filename,
         ResponseInterface $response,
diff --git a/tests/_support/_generated/JsonapiTesterActions.php b/tests/_support/_generated/JsonapiTesterActions.php
index 9cf61187d4762e2dcde9d7c78a40ad11f4809e87..8ce30a852cdc179404e97ba6db92bce11aa4d22c 100644
--- a/tests/_support/_generated/JsonapiTesterActions.php
+++ b/tests/_support/_generated/JsonapiTesterActions.php
@@ -1,4 +1,4 @@
-<?php  //[STAMP] 9a0bbbffd781acee72848c128782d162
+<?php  //[STAMP] bbf0b6e04dd36dd3e207bf34a7630c84
 // phpcs:ignoreFile
 namespace _generated;
 
@@ -1751,8 +1751,6 @@ trait JsonapiTesterActions
      * @param callable $function
      *
      * @return mixed
-     *
-     * @SuppressWarnings(PHPMD.Superglobals)
      * @see \Helper\Jsonapi::withPHPLib()
      */
     public function withPHPLib($credentials, $function) {
@@ -1760,6 +1758,21 @@ trait JsonapiTesterActions
     }
 
  
+    /**
+     * [!] Method is generated. Documentation taken from corresponding module.
+     *
+     * @param string $route the name of the invocable JSONAPI route class
+     * @param array $credentials the credentials for this request
+     * @param array $args additional arguments usually from the URL
+     * @param callable(JsonApiRequestBuilder): void $callback callback to customize the request that will be send to the
+     *                                                        route
+     * @see \Helper\Jsonapi::callJsonApi()
+     */
+    public function callJsonApi(string $route, array $credentials, array $args = [], $callback = NULL): \WoohooLabs\Yang\JsonApi\Response\JsonApiResponse {
+        return $this->getScenario()->runStep(new \Codeception\Step\Action('callJsonApi', func_get_args()));
+    }
+
+ 
     /**
      * [!] Method is generated. Documentation taken from corresponding module.
      *
@@ -1803,6 +1816,28 @@ trait JsonapiTesterActions
     }
 
  
+    /**
+     * [!] Method is generated. Documentation taken from corresponding module.
+     *
+     *
+     * @see \Helper\Jsonapi::getContainerBuilder()
+     */
+    public function getContainerBuilder(): \DI\ContainerBuilder {
+        return $this->getScenario()->runStep(new \Codeception\Step\Action('getContainerBuilder', func_get_args()));
+    }
+
+ 
+    /**
+     * [!] Method is generated. Documentation taken from corresponding module.
+     *
+     *
+     * @see \Helper\Jsonapi::getContainer()
+     */
+    public function getContainer(): \Psr\Container\ContainerInterface {
+        return $this->getScenario()->runStep(new \Codeception\Step\Action('getContainer', func_get_args()));
+    }
+
+ 
     /**
      * [!] Method is generated. Documentation taken from corresponding module.
      *
diff --git a/tests/jsonapi/ActivityStreamShowTest.php b/tests/jsonapi/ActivityStreamShowTest.php
index e841f97ae1f61b08809cdf43ff11d24a12047181..c20ec0a0ef8f16346e1361cd8e1761ea942d99d7 100644
--- a/tests/jsonapi/ActivityStreamShowTest.php
+++ b/tests/jsonapi/ActivityStreamShowTest.php
@@ -1,6 +1,5 @@
 <?php
 
-
 use JsonApi\Routes\ActivityStreamShow;
 
 class ActivityStreamShowTest extends \Codeception\Test\Unit
@@ -23,54 +22,11 @@ class ActivityStreamShowTest extends \Codeception\Test\Unit
     public function testShowEmptyStream()
     {
         $credentials = $this->tester->getCredentialsForTestAutor();
-
-        $response = $this->getActivityStreamForUser($credentials);
+        $response = $this->tester->callJsonApi(ActivityStreamShow::class, $credentials, ['id' => $credentials['id']]);
         $this->tester->assertTrue($response->isSuccessfulDocument([200]));
 
         $document = $response->document();
         $this->tester->assertTrue($document->isResourceCollectionDocument());
         $this->tester->assertEmpty($document->primaryResources());
     }
-
-    /*
-    public function testShowNotEmptyStream()
-    {
-        $credentials = $this->tester->getCredentialsForTestAutor();
-        $content = 'Eneios likes water';
-        $this->createBlubberActivity($credentials, $content);
-
-        $response = $this->getActivityStreamForUser($credentials);
-        $this->tester->assertTrue($response->isSuccessfulDocument([200]));
-
-        $document = $response->document();
-        $this->tester->assertTrue($document->isResourceCollectionDocument());
-
-        $resources = $document->primaryResources();
-        $this->tester->assertNotEmpty($resources);
-
-        $resource = current($resources);
-        $this->assertContains($content, $resource->attribute('content'));
-    }
-    */
-
-    // **** helper functions ****
-    private function getActivityStreamForUser($credentials)
-    {
-        $app = $this->tester->createApp($credentials, 'get', '/users/{id}/activitystream', ActivityStreamShow::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder
-            ->setUri('/users/'.$credentials['id'].'/activitystream')
-            ->fetch();
-
-        return $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
-    }
-
-    /*
-    private function createBlubberActivity($credentials, $content)
-    {
-        $posting = $this->createBlubberForUser($credentials, $content);
-        \Studip\Activity\BlubberProvider::postActivity('ignored', $posting, true);
-    }
-    */
 }
diff --git a/tests/jsonapi/BlubberCommentsByThreadIndexTest.php b/tests/jsonapi/BlubberCommentsByThreadIndexTest.php
index a437fa0b7667767f43291b550692530bc4bfac88..4d637958f508b87550385d372ea7e162916c215e 100644
--- a/tests/jsonapi/BlubberCommentsByThreadIndexTest.php
+++ b/tests/jsonapi/BlubberCommentsByThreadIndexTest.php
@@ -31,15 +31,10 @@ class BlubberCommentsByThreadIndexTest extends \Codeception\Test\Unit
         $credentials = $this->tester->getCredentialsForTestAutor();
         $thread = $this->createPublicBlubberThreadForUser($credentials, 'Who knows Daskylos?');
 
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $oldUser = $GLOBALS['user'] ?? null;
-        $GLOBALS['user'] = new \Seminar_User(\User::find($credentials['id']));
-
-        $this->createBlubberComment($credentials, $thread, 'Autolykos knows him.');
-        $this->createBlubberComment($credentials, $thread, 'Butes knows him too.');
-
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $GLOBALS['user'] = $oldUser;
+        $this->tester->withPHPLib($credentials, function ($credentials) use ($thread) {
+            $this->createBlubberComment($credentials, $thread, 'Autolykos knows him.');
+            $this->createBlubberComment($credentials, $thread, 'Butes knows him too.');
+        });
 
         $response = $this->fetchComments($credentials, $thread);
 
diff --git a/tests/jsonapi/BlubberCommentsCreateTest.php b/tests/jsonapi/BlubberCommentsCreateTest.php
index e72a3d6e3aa86b6b564d2a1e5fe7f5bae8ea2df7..d638a8ef98d955196e0a8c5e23f010177d7e92f9 100644
--- a/tests/jsonapi/BlubberCommentsCreateTest.php
+++ b/tests/jsonapi/BlubberCommentsCreateTest.php
@@ -62,14 +62,11 @@ class BlubberCommentsCreateTest extends \Codeception\Test\Unit
             ]
         ];
 
-        $app = $this->tester->createApp($credentials, 'post', '/blubber-threads/{id}/comments', CommentsCreate::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder
-            ->setUri('/blubber-threads/' . $thread->id . '/comments')
-            ->create()
-            ->setJsonApiBody($body);
-
-        return $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+        return $this->tester->callJsonApi(
+            CommentsCreate::class,
+            $credentials,
+            ['id' => $thread->id],
+            fn ($requestBuilder) => $requestBuilder->create()->setJsonApiBody($body)
+        );
     }
 }
diff --git a/tests/jsonapi/BlubberCommentsDeleteTest.php b/tests/jsonapi/BlubberCommentsDeleteTest.php
index cbe4b7b07ab31ef86d10f9b38f4a3be674966cd2..ea607a8fdc6ccd55ecd063b54d9a2f16cc5a4ed8 100644
--- a/tests/jsonapi/BlubberCommentsDeleteTest.php
+++ b/tests/jsonapi/BlubberCommentsDeleteTest.php
@@ -5,6 +5,9 @@ use JsonApi\Routes\Blubber\CommentsDelete;
 
 require_once 'BlubberTestHelper.php';
 
+/**
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ */
 class BlubberCommentsDeleteTest extends \Codeception\Test\Unit
 {
     use BlubberTestHelper;
@@ -31,17 +34,13 @@ class BlubberCommentsDeleteTest extends \Codeception\Test\Unit
         $credentials2 = $this->tester->getCredentialsForRoot();
         $thread = $this->createPublicBlubberThreadForUser($credentials2, 'Who knows Daskylos?');
 
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $oldUser = $GLOBALS['user'] ?? null;
-        $GLOBALS['user'] = new \Seminar_User(\User::find($credentials1['id']));
-
         $num = \BlubberComment::countBySQL('1');
-        $comment = $this->createBlubberComment($credentials1, $thread, 'Autolykos knows him.');
+        $comment = $this->tester->withPHPLib(
+            $credentials1,
+            fn() => $this->createBlubberComment($credentials1, $thread, 'Autolykos knows him.')
+        );
         $this->tester->assertEquals($num + 1, \BlubberComment::countBySQL('1'));
 
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $GLOBALS['user'] = $oldUser;
-
         $response = $this->deleteBlubberCommentJSONAPI($credentials2, $comment);
         $this->tester->assertSame(204, $response->getStatusCode());
 
@@ -50,13 +49,11 @@ class BlubberCommentsDeleteTest extends \Codeception\Test\Unit
 
     private function deleteBlubberCommentJSONAPI(array $credentials, \BlubberComment $comment)
     {
-        $app = $this->tester->createApp($credentials, 'delete', '/blubber-comments/{id}', CommentsDelete::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder
-            ->setUri('/blubber-comments/' . $comment->id)
-            ->delete();
-
-        return $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+        return $this->tester->callJsonApi(
+            CommentsDelete::class,
+            $credentials,
+            ['id' => $comment->id],
+            fn($requestBuilder) => $requestBuilder->delete()
+        );
     }
 }
diff --git a/tests/jsonapi/BlubberCommentsShowTest.php b/tests/jsonapi/BlubberCommentsShowTest.php
index d041fae6b580d454ea82a43873216f0998c1dfd1..608cd66878a88855e81393722b373596e464187f 100644
--- a/tests/jsonapi/BlubberCommentsShowTest.php
+++ b/tests/jsonapi/BlubberCommentsShowTest.php
@@ -27,14 +27,10 @@ class BlubberCommentsShowTest extends \Codeception\Test\Unit
         $credentials = $this->tester->getCredentialsForTestAutor();
         $thread = $this->createPublicBlubberThreadForUser($credentials, 'Who knows Daskylos?');
 
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $oldUser = $GLOBALS['user'] ?? null;
-        $GLOBALS['user'] = new \Seminar_User(\User::find($credentials['id']));
-
-        $comment = $this->createBlubberComment($credentials, $thread, 'Autolykos knows him.');
-
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $GLOBALS['user'] = $oldUser;
+        $comment = $this->tester->withPHPLib(
+            $credentials,
+            fn() => $this->createBlubberComment($credentials, $thread, 'Autolykos knows him.')
+        );
 
         $response = $this->fetchComment($credentials, $comment);
 
diff --git a/tests/jsonapi/BlubberCommentsUpdateTest.php b/tests/jsonapi/BlubberCommentsUpdateTest.php
index d9f4a1e705baaf80ea7a3fb3cc3a7aa9e6425983..10e7229905c267a5e141321f117e22c7c3ce6e0e 100644
--- a/tests/jsonapi/BlubberCommentsUpdateTest.php
+++ b/tests/jsonapi/BlubberCommentsUpdateTest.php
@@ -78,19 +78,16 @@ class BlubberCommentsUpdateTest extends \Codeception\Test\Unit
                 'id' => $comment->id,
                 'type' => Schema::TYPE,
                 'attributes' => [
-                    'content' => $content
-                ]
-            ]
+                    'content' => $content,
+                ],
+            ],
         ];
 
-        $app = $this->tester->createApp($credentials, 'patch', '/blubber-comments/{id}', CommentsUpdate::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder
-            ->setUri('/blubber-comments/' . $comment->id)
-            ->setJsonApiBody($body)
-            ->update();
-
-        return $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+        return $this->tester->callJsonApi(
+            CommentsUpdate::class,
+            $credentials,
+            ['id' => $comment->id],
+            fn($requestBuilder) => $requestBuilder->setJsonApiBody($body)->update()
+        );
     }
 }
diff --git a/tests/jsonapi/BlubberMentionsRelationshipTest.php b/tests/jsonapi/BlubberMentionsRelationshipTest.php
index a2dfe447845e6debc2d2412ed23a2350623eb193..b4dbe4a90d6262c5d3f1fe55387c9073a8044c96 100644
--- a/tests/jsonapi/BlubberMentionsRelationshipTest.php
+++ b/tests/jsonapi/BlubberMentionsRelationshipTest.php
@@ -30,16 +30,7 @@ class BlubberMentionsRelationshipTest extends \Codeception\Test\Unit
 
         $thread = $this->createPrivateBlubberThreadForUser($credentials, [$credentials]);
 
-        $app = $this->tester->createApp(
-            $credentials,
-            'get',
-            '/blubber-threads/{id}/relationships/mentions',
-            Mentions::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder->setUri('/blubber-threads/'.$thread->id.'/relationships/mentions')->fetch();
-
-        $response = $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+        $response = $this->tester->callJsonApi(Mentions::class, $credentials, ['id' => $thread->id]);
         $this->tester->assertTrue($response->isSuccessfulDocument([200]));
 
         $document = $response->document();
@@ -56,18 +47,13 @@ class BlubberMentionsRelationshipTest extends \Codeception\Test\Unit
         $thread = $this->createPrivateBlubberThreadForUser($credentials, [$credentials]);
         $this->tester->assertCount(1, $thread->mentions);
 
-        $app = $this->tester->createApp(
+        $body = $this->prepareValidBody([$this->tester->getCredentialsForTestDozent()]);
+        $response = $this->tester->callJsonApi(
+            Mentions::class,
             $credentials,
-            'post',
-            '/blubber-threads/{id}/relationships/mentions',
-            Mentions::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder->setUri('/blubber-threads/'.$thread->id.'/relationships/mentions')
-                       ->create()
-                       ->setJsonApiBody($this->prepareValidBody([$this->tester->getCredentialsForTestDozent()]));
-
-        $response = $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+            ['id' => $thread->id],
+            fn($requestBuilder) => $requestBuilder->create()->setJsonApiBody($body)
+        );
 
         $this->tester->assertSame(204, $response->getStatusCode());
         $this->tester->assertCount(2, \BlubberThread::find($thread->id)->mentions);
@@ -79,39 +65,27 @@ class BlubberMentionsRelationshipTest extends \Codeception\Test\Unit
         $credentials2 = $this->tester->getCredentialsForTestDozent();
         $credentials3 = $this->tester->getCredentialsForTestAdmin();
 
-        $thread = $this->createPrivateBlubberThreadForUser($credentials1, [$credentials1, $credentials2, $credentials3]);
+        $thread = $this->createPrivateBlubberThreadForUser($credentials1, [
+            $credentials1,
+            $credentials2,
+            $credentials3,
+        ]);
         $this->tester->assertCount(3, $thread->mentions);
 
-        $app = $this->tester->createApp(
+        $body = $this->prepareValidBody([$credentials1]);
+        $response = $this->tester->callJsonApi(
+            Mentions::class,
             $credentials1,
-            'delete',
-            '/blubber-threads/{id}/relationships/mentions',
-            Mentions::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials1);
-        $requestBuilder->setUri('/blubber-threads/'.$thread->id.'/relationships/mentions')
-                       ->delete()
-                       ->setJsonApiBody($this->prepareValidBody([$credentials1]));
-
-        $response = $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+            ['id' => $thread->id],
+            fn($requestBuilder) => $requestBuilder->delete()->setJsonApiBody($body)
+        );
 
         $this->tester->assertSame(204, $response->getStatusCode());
         $this->tester->assertCount(2, \BlubberThread::find($thread->id)->mentions);
     }
 
-
     private function prepareValidBody(array $users)
     {
-        return [
-            'data' => array_map(
-                function ($user) {
-                    return [
-                        'type' => UsersSchema::TYPE,
-                        'id' => $user['id'],
-                    ];
-                },
-                $users
-            ),
-        ];
+        return ['data' => array_map(fn($user) => ['type' => UsersSchema::TYPE, 'id' => $user['id']], $users)];
     }
 }
diff --git a/tests/jsonapi/BlubberTestHelper.php b/tests/jsonapi/BlubberTestHelper.php
index e4241d4a133be264f216865f6fad9a0522858659..effd6f2cab172413ef16be9a1f776c925b345e9f 100644
--- a/tests/jsonapi/BlubberTestHelper.php
+++ b/tests/jsonapi/BlubberTestHelper.php
@@ -4,38 +4,38 @@ use JsonApi\Routes\Blubber\ThreadsShow;
 use JsonApi\Routes\Blubber\CommentsByThreadIndex;
 use JsonApi\Routes\Blubber\CommentsShow;
 
+/**
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
 trait BlubberTestHelper
 {
     private function createPublicBlubberThreadForUser(array $credentials, string $content = '')
     {
-        $blubber = \BlubberThread::create(
-            [
-                'context_type' => 'public',
-                'context_id' => $credentials['id'],
-                'content' => $content,
-                'user_id' => $credentials['id'],
-                'external_contact' => 0,
-                'visible_in_stream' => 1,
-                'commentable' => 1,
-            ]
-        );
+        $blubber = \BlubberThread::create([
+            'context_type' => 'public',
+            'context_id' => $credentials['id'],
+            'content' => $content,
+            'user_id' => $credentials['id'],
+            'external_contact' => 0,
+            'visible_in_stream' => 1,
+            'commentable' => 1,
+        ]);
 
         return \BlubberThread::find($blubber->id);
     }
 
     private function createPrivateBlubberThreadForUser(array $credentials, array $mentions, string $content = '')
     {
-        $blubber = \BlubberThread::create(
-            [
-                'context_type' => 'private',
-                'context_id' => '',
-                'content' => $content,
-                'user_id' => $credentials['id'],
-                'external_contact' => 0,
-                'visible_in_stream' => 1,
-                'commentable' => 1,
-            ]
-        );
+        $blubber = \BlubberThread::create([
+            'context_type' => 'private',
+            'context_id' => '',
+            'content' => $content,
+            'user_id' => $credentials['id'],
+            'external_contact' => 0,
+            'visible_in_stream' => 1,
+            'commentable' => 1,
+        ]);
 
         foreach ($mentions as $mention) {
             \BlubberMention::create(['thread_id' => $blubber->id, 'user_id' => $mention['id']]);
@@ -46,107 +46,71 @@ trait BlubberTestHelper
 
     private function createCourseBlubberThreadForUser(array $credentials, string $courseId, string $content = '')
     {
-        $blubber = \BlubberThread::create(
-            [
-                'context_type' => 'course',
-                'context_id' => $courseId,
-                'content' => $content,
-                'user_id' => $credentials['id'],
-                'external_contact' => 0,
-                'visible_in_stream' => 1,
-                'commentable' => 1,
-            ]
-        );
+        $blubber = \BlubberThread::create([
+            'context_type' => 'course',
+            'context_id' => $courseId,
+            'content' => $content,
+            'user_id' => $credentials['id'],
+            'external_contact' => 0,
+            'visible_in_stream' => 1,
+            'commentable' => 1,
+        ]);
 
         return \BlubberThread::find($blubber->id);
     }
 
-    private function createInstituteBlubberThreadForUser(array $credentials, \Institute $institute, string $content = '')
-    {
-        $blubber = \BlubberThread::create(
-            [
-                'context_type' => 'institute',
-                'context_id' => $institute->id,
-                'content' => $content,
-                'user_id' => $credentials['id'],
-                'external_contact' => 0,
-                'visible_in_stream' => 1,
-                'commentable' => 1,
-            ]
-        );
+    private function createInstituteBlubberThreadForUser(
+        array $credentials,
+        \Institute $institute,
+        string $content = ''
+    ) {
+        $blubber = \BlubberThread::create([
+            'context_type' => 'institute',
+            'context_id' => $institute->id,
+            'content' => $content,
+            'user_id' => $credentials['id'],
+            'external_contact' => 0,
+            'visible_in_stream' => 1,
+            'commentable' => 1,
+        ]);
 
         return \BlubberThread::find($blubber->id);
     }
 
-    /**
-     * @SuppressWarnings(PHPMD.Superglobals)
-     */
     private function createBlubberComment(array $credentials, \BlubberThread $thread, $content)
     {
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $oldUser = $GLOBALS['user'] ?? null;
-        $GLOBALS['user'] = new \Seminar_User(\User::find($credentials['id']));
-
-        $blubber = \BlubberComment::create(
-            [
-                'thread_id' => $thread->id,
-                'content' => $content,
-                'user_id' => $credentials['id'],
-            ]
+        return $this->tester->withPHPLib(
+            $credentials,
+            fn() => \BlubberComment::find(
+                \BlubberComment::create([
+                    'thread_id' => $thread->id,
+                    'content' => $content,
+                    'user_id' => $credentials['id'],
+                ])->id
+            )
         );
-
-        // Workaround old-style Stud.IP-API using $GLOBALS['user']
-        $GLOBALS['user'] = $oldUser;
-
-
-        return \BlubberComment::find($blubber->id);
     }
 
     private function fetchThread(array $credentials, \BlubberThread $resource)
     {
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp($credentials, 'get', '/blubber-threads/{id}', ThreadsShow::class),
-            $this->tester
-            ->createRequestBuilder($credentials)
-            ->setUri('/blubber-threads/'.$resource->id)
-            ->fetch()
-            ->getRequest()
-        );
+        return $this->tester->callJsonApi(ThreadsShow::class, $credentials, ['id' => $resource->id]);
     }
 
     private function fetchComments(array $credentials, \BlubberThread $resource)
     {
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp($credentials, 'get', '/blubber-threads/{id}/comments', CommentsByThreadIndex::class),
-            $this->tester
-            ->createRequestBuilder($credentials)
-            ->setUri('/blubber-threads/'.$resource->id.'/comments')
-            ->fetch()
-            ->getRequest()
-        );
+        return $this->tester->callJsonApi(CommentsByThreadIndex::class, $credentials, ['id' => $resource->id]);
     }
 
     private function fetchComment(array $credentials, \BlubberComment $resource)
     {
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp($credentials, 'get', '/blubber-comments/{id}', CommentsShow::class),
-            $this->tester
-            ->createRequestBuilder($credentials)
-            ->setUri('/blubber-comments/'.$resource->id)
-            ->fetch()
-            ->getRequest()
-        );
+        return $this->tester->callJsonApi(CommentsShow::class, $credentials, ['id' => $resource->id]);
     }
 
     private function upgradeAndFilterThreads(array $credentials, array $threads)
     {
         return array_filter(
-            array_map(function ($thread) {
-                return \BlubberThread::upgradeThread($thread);
-            }, $threads),
-            function ($thread) use ($credentials) {
-                return $thread->isVisibleInStream() && $thread->isReadable($credentials['id']);
-            }
+            array_map(fn($thread) => \BlubberThread::upgradeThread($thread), $threads),
+            fn($thread) => $thread->isVisibleInStream() && $thread->isReadable($credentials['id'])
         );
     }
 }
diff --git a/tests/jsonapi/BlubberThreadsCreateTest.php b/tests/jsonapi/BlubberThreadsCreateTest.php
index d2bdaea1a7eaa64b9beab279d3b0fa5c6885d5c4..75ceb6c50908ab4e860edaebe270114c38258463 100644
--- a/tests/jsonapi/BlubberThreadsCreateTest.php
+++ b/tests/jsonapi/BlubberThreadsCreateTest.php
@@ -85,26 +85,22 @@ class BlubberThreadsCreateTest extends \Codeception\Test\Unit
         $this->tester->assertSame(400, $response->getStatusCode());
     }
 
-
     private function createThread($credentials, $contextType = 'private')
     {
         $body = [
             'data' => [
                 'type' => Schema::TYPE,
                 'attributes' => [
-                    'context-type' => $contextType
-                ]
-            ]
+                    'context-type' => $contextType,
+                ],
+            ],
         ];
 
-        $app = $this->tester->createApp($credentials, 'post', '/blubber-threads', ThreadsCreate::class);
-
-        $requestBuilder = $this->tester->createRequestBuilder($credentials);
-        $requestBuilder
-            ->setUri('/blubber-threads')
-            ->create()
-            ->setJsonApiBody($body);
-
-        return $this->tester->sendMockRequest($app, $requestBuilder->getRequest());
+        return $this->tester->callJsonApi(
+            ThreadsCreate::class,
+            $credentials,
+            [],
+            fn($requestBuilder) => $requestBuilder->create()->setJsonApiBody($body)
+        );
     }
 }
diff --git a/tests/jsonapi/BlubberThreadsIndexTest.php b/tests/jsonapi/BlubberThreadsIndexTest.php
index 14173d3278ad3eb738b96b12bcdaec2cc584caa2..f65c5e95c62ec89161a3258d4c3328e7e145f91d 100644
--- a/tests/jsonapi/BlubberThreadsIndexTest.php
+++ b/tests/jsonapi/BlubberThreadsIndexTest.php
@@ -4,6 +4,10 @@ use JsonApi\Routes\Blubber\ThreadsIndex;
 
 require_once 'BlubberTestHelper.php';
 
+/**
+ * @SuppressWarnings(PHPMD.StaticAccess)
+ * @SuppressWarnings(PHPMD.Superglobals)
+ */
 class BlubberThreadsIndexTest extends \Codeception\Test\Unit
 {
     use BlubberTestHelper;
@@ -34,9 +38,10 @@ class BlubberThreadsIndexTest extends \Codeception\Test\Unit
         // given
         $credentials = $this->tester->getCredentialsForTestAutor();
 
-        $num = $this->tester->withPHPLib($credentials, function ($credentials) {
-            return count(\BlubberThread::findMyGlobalThreads(9999, null, null, $credentials['id']));
-        });
+        $num = $this->tester->withPHPLib(
+            $credentials,
+            fn() => count(\BlubberThread::findMyGlobalThreads(9999, null, null, $credentials['id']))
+        );
 
         $response = $this->fetchAllThreads($credentials);
 
@@ -104,9 +109,10 @@ class BlubberThreadsIndexTest extends \Codeception\Test\Unit
 
         $this->createCourseBlubberThreadForUser($credentials, $courseId, 'I have seen Eribotes!');
 
-        $num = $this->tester->withPHPLib($credentials, function ($credentials) use ($courseId) {
-            return count(\BlubberThread::findBySeminar($courseId, false, $credentials['id']));
-        });
+        $num = $this->tester->withPHPLib(
+            $credentials,
+            fn() => count(\BlubberThread::findBySeminar($courseId, false, $credentials['id']))
+        );
 
         $response = $this->fetchCourseThreads($credentials, $courseId);
 
@@ -136,9 +142,10 @@ class BlubberThreadsIndexTest extends \Codeception\Test\Unit
 
         $this->createInstituteBlubberThreadForUser($credentials, $institute, 'I have seen Eribotes!');
 
-        $num = $this->tester->withPHPLib($credentials, function ($credentials) use ($institute) {
-            return count(\BlubberThread::findByInstitut($institute->id, false, $credentials['id']));
-        });
+        $num = $this->tester->withPHPLib(
+            $credentials,
+            fn() => count(\BlubberThread::findByInstitut($institute->id, false, $credentials['id']))
+        );
 
         $response = $this->fetchInstituteThreads($credentials, $institute->id);
 
@@ -167,32 +174,37 @@ class BlubberThreadsIndexTest extends \Codeception\Test\Unit
 
         // assert that there are no BlubberThreads since now
         $now = new DateTime();
-        $threads = $this->tester->withPHPLib($credentials, function ($credentials) use ($now) {
-            return \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp(), null, $credentials['id']);
-        });
+        $threads = $this->tester->withPHPLib(
+            $credentials,
+            fn() => \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp(), null, $credentials['id'])
+        );
         $this->tester->assertCount(0, $threads);
 
         $response = $this->fetchAllThreads($credentials, ['since' => $now->format(\DATE_ATOM)]);
         $this->tester->assertCount(0, $response->document()->primaryResources());
 
-
         // now create one new BlubberThread and assert its presence
         $thread = $this->createPrivateBlubberThreadForUser($credentials, [$credentials], 'some clever content');
-        $threads = $this->tester->withPHPLib($credentials, function ($credentials) use ($now) {
-            return \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp() - 1, null, $credentials['id']);
-        });
+        $threads = $this->tester->withPHPLib(
+            $credentials,
+            fn() => \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp() - 1, null, $credentials['id'])
+        );
         $this->tester->assertCount(1, $threads);
 
         $pivot = $thread['chdate'];
-        $this->tester->assertTrue((new DateTime("@".$pivot))->getTimestamp() == $thread['chdate']);
+        $this->tester->assertTrue((new DateTime('@' . $pivot))->getTimestamp() == $thread['chdate']);
 
         // assert that there is one thread since (inclusive) pivot
-        $response = $this->fetchAllThreads($credentials, ['since' => (new DateTime("@".($pivot - 1)))->format(\DATE_ATOM)]);
+        $response = $this->fetchAllThreads($credentials, [
+            'since' => (new DateTime('@' . ($pivot - 1)))->format(\DATE_ATOM),
+        ]);
         $this->tester->assertCount(1, $threads = $response->document()->primaryResources());
         $this->tester->assertSame($threads[0]->id(), $thread->id);
 
         // assert that there is no thread later than (not inclusive) pivot
-        $response = $this->fetchAllThreads($credentials, ['since' => (new DateTime("@".($pivot - 1)))->modify('+1 second')->format(\DATE_ATOM)]);
+        $response = $this->fetchAllThreads($credentials, [
+            'since' => (new DateTime('@' . ($pivot - 1)))->modify('+1 second')->format(\DATE_ATOM),
+        ]);
         $this->tester->assertCount(0, $response->document()->primaryResources());
     }
 
@@ -203,134 +215,76 @@ class BlubberThreadsIndexTest extends \Codeception\Test\Unit
 
         // assert that there are no BlubberThreads since now
         $now = new DateTime();
-        $threads = $this->tester->withPHPLib($credentials, function ($credentials) use ($now) {
-            return \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp(), null, $credentials['id']);
-        });
+        $threads = $this->tester->withPHPLib(
+            $credentials,
+            fn() => \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp(), null, $credentials['id'])
+        );
         $this->tester->assertCount(0, $threads);
 
         // now create one new BlubberThread and assert its presence
         $thread = $this->createPrivateBlubberThreadForUser($credentials, [$credentials], 'some clever content');
-        $threads = $this->tester->withPHPLib($credentials, function ($credentials) use ($now) {
-            return \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp() - 1, null, $credentials['id']);
-        });
+        $threads = $this->tester->withPHPLib(
+            $credentials,
+            fn() => \BlubberThread::findMyGlobalThreads(9999, $now->getTimestamp() - 1, null, $credentials['id'])
+        );
         $this->tester->assertCount(1, $threads);
 
         $pivot = $thread['chdate'];
-        $this->tester->assertTrue((new DateTime("@".$pivot))->getTimestamp() == $thread['chdate']);
+        $this->tester->assertTrue((new DateTime('@' . $pivot))->getTimestamp() == $thread['chdate']);
 
         // count all the threads
-        $countAllThreads = $this->tester->withPHPLib($credentials, function ($credentials) use ($now) {
-            return count(\BlubberThread::findMyGlobalThreads(9999, null, null, $credentials['id']));
-        });
+        $countAllThreads = $this->tester->withPHPLib(
+            $credentials,
+            fn() => count(\BlubberThread::findMyGlobalThreads(9999, null, null, $credentials['id']))
+        );
         $this->tester->assertTrue($countAllThreads > 0);
 
         // assert that we get all the threads before (exclusive) pivot
-        $response = $this->fetchAllThreads($credentials, ['before' => (new DateTime("@".($pivot + 1)))->format(\DATE_ATOM)]);
+        $response = $this->fetchAllThreads($credentials, [
+            'before' => (new DateTime('@' . ($pivot + 1)))->format(\DATE_ATOM),
+        ]);
         $this->tester->assertCount($countAllThreads, $threads = $response->document()->primaryResources());
         $this->tester->assertSame($threads[0]->id(), $thread->id);
 
         // assert that we get all the threads minus 1 before (exclusive) pivot
-        $response = $this->fetchAllThreads($credentials, ['before' => (new DateTime("@".($pivot + 1)))->modify("-1 seconds")->format(\DATE_ATOM)]);
+        $response = $this->fetchAllThreads($credentials, [
+            'before' => (new DateTime('@' . ($pivot + 1)))->modify('-1 seconds')->format(\DATE_ATOM),
+        ]);
         $this->tester->assertCount($countAllThreads - 1, $threads = $response->document()->primaryResources());
     }
 
-    private function fetchAllThreads(array $credentials, array $filters = [])
+    private function fetchThreads(array $args, array $credentials, array $filters = [])
     {
-        $requestBuilder = $this->tester
-                        ->createRequestBuilder($credentials)
-                        ->setUri('/blubber-threads/all')
-                        ->fetch();
-
-        if (count($filters)) {
-            $requestBuilder->setJsonApiFilter($filters);
-        }
-
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp($credentials, 'get', '/blubber-threads/{type:all}', ThreadsIndex::class),
-            $requestBuilder->getRequest()
+        return $this->tester->callJsonApi(
+            ThreadsIndex::class,
+            $credentials,
+            $args,
+            fn($requestBuilder) => $requestBuilder->setJsonApiFilter($filters)
         );
     }
 
-    private function fetchPublicThreads(array $credentials, array $filters = [])
+    private function fetchAllThreads(array $credentials, array $filters = [])
     {
-        $requestBuilder = $this->tester
-                        ->createRequestBuilder($credentials)
-                        ->setUri('/studip/blubber-threads/public')
-                        ->fetch();
-
-        if (count($filters)) {
-            $requestBuilder->setJsonApiFilter($filters);
-        }
-
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp($credentials, 'get', '/studip/blubber-threads/{type:public}', ThreadsIndex::class),
-            $requestBuilder->getRequest()
-        );
+        return $this->fetchThreads(['type' => 'all'], $credentials, $filters);
     }
 
-    private function fetchCourseThreads
-        (array $credentials, string $courseId, array $filters = [])
+    private function fetchPublicThreads(array $credentials, array $filters = [])
     {
-        $requestBuilder = $this->tester
-                        ->createRequestBuilder($credentials)
-                        ->setUri('/courses/'.$courseId.'/blubber-threads/course')
-                        ->fetch();
-        if (count($filters)) {
-            $requestBuilder->setJsonApiFilter($filters);
-        }
+        return $this->fetchThreads(['type' => 'public'], $credentials, $filters);
+    }
 
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp(
-                $credentials,
-                'get',
-                '/courses/{id}/blubber-threads/{type:course}',
-                ThreadsIndex::class
-            ),
-            $requestBuilder->getRequest()
-        );
+    private function fetchCourseThreads(array $credentials, string $courseId, array $filters = [])
+    {
+        return $this->fetchThreads(['type' => 'course', 'id' => $courseId], $credentials, $filters);
     }
 
     private function fetchInstituteThreads(array $credentials, string $instituteId, array $filters = [])
     {
-        $requestBuilder = $this->tester
-                        ->createRequestBuilder($credentials)
-                        ->setUri('/institutes/'.$instituteId.'/blubber-threads/institute')
-                        ->fetch();
-
-        if (count($filters)) {
-            $requestBuilder->setJsonApiFilter($filters);
-        }
-
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp(
-                $credentials,
-                'get',
-                '/institutes/{id}/blubber-threads/{type:institute}',
-                ThreadsIndex::class
-            ),
-            $requestBuilder->getRequest()
-        );
+        return $this->fetchThreads(['type' => 'institute', 'id' => $instituteId], $credentials, $filters);
     }
 
     private function fetchPrivateThreads(array $credentials1, array $credentials2, array $filters = [])
     {
-        $requestBuilder = $this->tester
-                        ->createRequestBuilder($credentials1)
-                        ->setUri('/users/'.$credentials2['id'].'/blubber-threads/private')
-                        ->fetch();
-
-        if (count($filters)) {
-            $requestBuilder->setJsonApiFilter($filters);
-        }
-
-        return $this->tester->sendMockRequest(
-            $this->tester->createApp(
-                $credentials1,
-                'get',
-                '/users/{id}/blubber-threads/{type:private}',
-                ThreadsIndex::class
-            ),
-            $requestBuilder->getRequest()
-        );
+        return $this->fetchThreads(['type' => 'private', 'id' => $credentials2['id']], $credentials1, $filters);
     }
 }
diff --git a/tests/jsonapi/CommentsShowTest.php b/tests/jsonapi/CommentsShowTest.php
index d57c3356a6b23030de05be31521ae9c3d7073a8c..00ec4e9ee866d136f3037b1d1c7cf38d3ddcfde2 100644
--- a/tests/jsonapi/CommentsShowTest.php
+++ b/tests/jsonapi/CommentsShowTest.php
@@ -30,9 +30,7 @@ class CommentsShowTest extends \Codeception\Test\Unit
         $content = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit';
         $news = $this->createNews($credentials, $title, $content);
 
-        $newsId = $news->id;
-
-        $response = $this->getComments($credentials, $newsId);
+        $response = $this->tester->callJsonApi(CommentsIndex::class, $credentials, ['id' => $news->id]);
     }
 
     public function testShowOneComment()
@@ -41,39 +39,11 @@ class CommentsShowTest extends \Codeception\Test\Unit
         $title = 'A testing title';
         $content = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit';
         $news = $this->createNews($credentials, $title, $content);
-
         $comment = $this->createComment($credentials, $news, $content);
 
-        $response = $this->getComment($credentials, $comment);
+        $response = $this->tester->callJsonApi(CommentsShow::class, $credentials, ['id' => $comment->id]);
         $this->tester->assertSame(200, $response->getStatusCode());
         $this->tester->assertTrue($response->isSuccessfulDocument([200]));
         $document = $response->document();
     }
-
-    //helpers:
-    private function getComments($credentials, $newsId)
-    {
-        $app = $this->tester->createApp($credentials, 'get', '/news/{id}/comments', CommentsIndex::class);
-
-        return $this->tester->sendMockRequest(
-                $app,
-                $this->tester->createRequestBuilder($credentials)
-                ->setUri('/news/'.$newsId.'/comments')
-                ->fetch()
-                ->getRequest()
-        );
-    }
-
-    private function getComment($credentials, $comment)
-    {
-        $app = $this->tester->createApp($credentials, 'get', '/comments/{id}', CommentsShow::class);
-
-        return $this->tester->sendMockRequest(
-                $app,
-                $this->tester->createRequestBuilder($credentials)
-                ->setUri('/comments/'.$comment->id)
-                ->fetch()
-                ->getRequest()
-        );
-    }
 }
diff --git a/tests/jsonapi/WikiShowTest.php b/tests/jsonapi/WikiShowTest.php
index c77aea98264aa1c4d6c988857fc810c4ca18249a..ad60e31c0a12d4c0b9d0950142f882f70e9f18ab 100644
--- a/tests/jsonapi/WikiShowTest.php
+++ b/tests/jsonapi/WikiShowTest.php
@@ -26,12 +26,13 @@ class WikiShowTest extends \Codeception\Test\Unit
         $rangeId = 'a07535cf2f8a72df33c12ddfa4b53dde';
 
         $keyword = 'NEU';
-        $content = 'Es gibt im Moment in diese Mannschaft, oh, einige Spieler vergessenihren Profi was sie sind. Ich lese nicht sehr viele Zeitungen, aberich habe gehört viele Situationen. Erstens: Wir haben nicht offensivgespielt. Es gibt keine deutsche Mannschaft spielt offensiv und dieNamen offensiv wie Bayern. Letzte Spiel hatten wir in Platz dreiSpitzen: Elber, Jancker und dann Zickler. Wir mussen nicht vergessenZickler. Zickler ist eine Spitzen mehr, Mehmet mehr Basler. Ist klardiese Wörter, ist möglich verstehen, was ich hab’ gesagt? Danke.';
+        $content =
+            'Es gibt im Moment in diese Mannschaft, oh, einige Spieler vergessenihren Profi was sie sind. Ich lese nicht sehr viele Zeitungen, aberich habe gehört viele Situationen. Erstens: Wir haben nicht offensivgespielt. Es gibt keine deutsche Mannschaft spielt offensiv und dieNamen offensiv wie Bayern. Letzte Spiel hatten wir in Platz dreiSpitzen: Elber, Jancker und dann Zickler. Wir mussen nicht vergessenZickler. Zickler ist eine Spitzen mehr, Mehmet mehr Basler. Ist klardiese Wörter, ist möglich verstehen, was ich hab’ gesagt? Danke.';
         $this->createWikiPage($rangeId, $keyword, $content);
-
         $this->tester->assertCount(1, \WikiPage::findBySQL('`range_id` = ?', [$rangeId]));
 
-        $response = $this->getWikiPage($credentials, $rangeId, $keyword);
+        $response = $this->tester->callJsonApi(WikiShow::class, $credentials, ['id' => $rangeId . '_' . $keyword]);
+
         $this->tester->assertTrue($response->isSuccessfulDocument([200]));
 
         $page = $response->document()->primaryResource();
@@ -39,39 +40,19 @@ class WikiShowTest extends \Codeception\Test\Unit
         $this->tester->assertEquals($content, $page->attribute('content'));
     }
 
-    //helpers:
-    private function getWikiPage($credentials, $rangeId, $keyword)
-    {
-        $app = $this->tester->createApp($credentials, 'get', '/wiki-pages/{id}', WikiShow::class, 'get-wiki-page');
-
-        return $this->tester->sendMockRequest(
-                $app,
-                $this->tester->createRequestBuilder($credentials)
-                ->setUri('/wiki-pages/'.$rangeId.'_'.$keyword)
-                ->fetch()
-                ->getRequest()
-        );
-    }
-
     private function createWikiPage($rangeId, $keyword, $content)
     {
-        $credentials = $this->tester->getCredentialsForTestDozent();
-        // EVIL HACK
-        $oldPerm = $GLOBALS['perm'] ?? null;
-        $oldUser = $GLOBALS['user'] ?? null;
-        $GLOBALS['perm'] = new \Seminar_Perm();
-        $GLOBALS['user'] = new \Seminar_User(\User::find($credentials['id']));
-
-        $wikiPage = new \WikiPage();
-        $wikiPage->name = $keyword;
-        $wikiPage->range_id = $rangeId;
-        $wikiPage->content = $content;
-        $wikiPage->user_id = 'nobody';
-        $wikiPage->store();
-
-        $GLOBALS['perm'] = $oldPerm;
-        $GLOBALS['user'] = $oldUser;
-
-        return $wikiPage;
+        return $this->tester->withPHPLib($this->tester->getCredentialsForTestDozent(), function () use (
+            $content,
+            $keyword,
+            $rangeId
+        ) {
+            return \WikiPage::create([
+                'content' => $content,
+                'name' => $keyword,
+                'range_id' => $rangeId,
+                'user_id' => 'nobody',
+            ]);
+        });
     }
 }