diff --git a/modules/cron/lib/Controller/Cron.php b/modules/cron/lib/Controller/Cron.php
index 0e6dd848907c5fd14e38513d7e28a6f82bb753dc..f895e0873170b7c137b3a1eaa0cd77e26e798c1a 100644
--- a/modules/cron/lib/Controller/Cron.php
+++ b/modules/cron/lib/Controller/Cron.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
 
 namespace SimpleSAML\Module\cron\Controller;
 
+use PHPMailer\PHPMailer\Exception as PHPMailerException;
 use SimpleSAML\Auth;
 use SimpleSAML\Auth\AuthenticationFactory;
 use SimpleSAML\Configuration;
@@ -15,6 +16,7 @@ use SimpleSAML\Session;
 use SimpleSAML\Utils;
 use SimpleSAML\XHTML\Template;
 use Symfony\Component\HttpFoundation\RedirectResponse;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 
 /**
@@ -35,6 +37,12 @@ class Cron
     /** @var \SimpleSAML\Session */
     protected $session;
 
+    /**
+     * @var \SimpleSAML\Utils\Auth|string
+     * @psalm-var \SimpleSAML\Utils\Auth|class-string
+     */
+    protected $authUtils = Utils\Auth::class;
+
 
     /**
      * Controller constructor.
@@ -57,18 +65,30 @@ class Cron
     }
 
 
+    /**
+     * Inject the \SimpleSAML\Utils\Auth dependency.
+     *
+     * @param \SimpleSAML\Utils\Auth $authUtils
+     */
+    public function setAuthUtils(Utils\Auth $authUtils): void
+    {
+        $this->authUtils = $authUtils;
+    }
+
+
     /**
      * Show cron info.
      *
+     * @param \Symfony\Component\HttpFoundation\Request $request
      * @return \SimpleSAML\XHTML\Template
      *   An HTML template or a redirection if we are not authenticated.
      */
-    public function info(): Template
+    public function info(Request $request): Template
     {
-        Utils\Auth::requireAdmin();
+        $this->authUtils::requireAdmin();
 
         $key = $this->cronconfig->getValue('key', 'secret');
-        $tags = $this->cronconfig->getValue('allowed_tags');
+        $tags = $this->cronconfig->getValue('allowed_tags', []);
 
         $def = [
             'weekly' => "22 0 * * 0",
@@ -98,6 +118,7 @@ class Cron
      *
      * This controller will start a cron operation
      *
+     * @param \Symfony\Component\HttpFoundation\Request $request
      * @param string $tag The tag
      * @param string $key The secret key
      * @param string $output The output format, defaulting to xhtml
@@ -107,7 +128,7 @@ class Cron
      *
      * @throws \SimpleSAML\Error\Exception
      */
-    public function run(string $tag, string $key, string $output = 'xhtml'): Response
+    public function run(Request $request, string $tag, string $key, string $output = 'xhtml'): Response
     {
         $configKey = $this->cronconfig->getValue('key', 'secret');
         if ($key !== $configKey) {
@@ -132,7 +153,7 @@ class Cron
             $mail->setData(['url' => $url, 'tag' => $croninfo['tag'], 'summary' => $croninfo['summary']]);
             try {
                 $mail->send();
-            } catch (\PHPMailer\PHPMailer\Exception $e) {
+            } catch (PHPMailerException $e) {
                 Logger::warning("Unable to send cron report; " . $e->getMessage());
             }
         }
diff --git a/modules/cron/lib/Cron.php b/modules/cron/lib/Cron.php
index 0966b8773fa876e43384b26860b5c497fc0e3ec5..7c6b0c50f0be0c0dec9c674012f43619fc7810c6 100644
--- a/modules/cron/lib/Cron.php
+++ b/modules/cron/lib/Cron.php
@@ -59,6 +59,7 @@ class Cron
             Logger::debug('Cron - Summary: ' . $s);
         }
 
+        /** @psalm-suppress NullableReturnStatement */
         return $croninfo;
     }
 
diff --git a/modules/cron/www/cron.php b/modules/cron/www/cron.php
deleted file mode 100644
index d77b307bed35618aa4cf9f365befa619ac9c0ad3..0000000000000000000000000000000000000000
--- a/modules/cron/www/cron.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-namespace SimpleSAML\Module\cron;
-
-use SimpleSAML\Configuration;
-use SimpleSAML\Session;
-use Symfony\Component\HttpFoundation\Request;
-
-$config = Configuration::getInstance();
-$session = Session::getSessionFromRequest();
-$request = Request::createFromGlobals();
-
-$tag = $request->get('tag');
-$key = $request->get('key');
-$output = $request->get('output');
-
-$controller = new Controller\Cron($config, $session);
-$response = $controller->run($tag, $key, $output);
-$response->send();
diff --git a/modules/cron/www/croninfo.php b/modules/cron/www/croninfo.php
deleted file mode 100644
index 1c9ec0da2bd782c8cad5884a06dc2e09b204a919..0000000000000000000000000000000000000000
--- a/modules/cron/www/croninfo.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-/**
- * The _include script registers a autoloader for the SimpleSAMLphp libraries. It also
- * initializes the SimpleSAMLphp config class with the correct path.
- */
-
-namespace SimpleSAML\Module\cron;
-
-use SimpleSAML\Configuration;
-use SimpleSAML\Session;
-
-$config = Configuration::getInstance();
-$session = Session::getSessionFromRequest();
-
-$controller = new Controller\Cron($config, $session);
-$response = $controller->info();
-$response->send();
diff --git a/phpunit.xml b/phpunit.xml
index d00aef1cc1b3b2d6cb1a62b197047db0b8e4c808..11413952c4d97a4a4dcc8f265952e4c8bec0c16f 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -19,6 +19,7 @@
             <directory suffix=".php">./lib/</directory>
             <directory suffix=".php">./modules/admin/lib/</directory>
             <directory suffix=".php">./modules/core/lib/</directory>
+            <directory suffix=".php">./modules/cron/lib/</directory>
             <directory suffix=".php">./modules/saml/lib/</directory>
             <exclude>
                 <directory>./vendor/</directory>
diff --git a/tests/modules/cron/lib/Controller/CronTest.php b/tests/modules/cron/lib/Controller/CronTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..4987618bf81d6a63c7bac4012b71fcf9af6d0323
--- /dev/null
+++ b/tests/modules/cron/lib/Controller/CronTest.php
@@ -0,0 +1,112 @@
+<?php
+
+declare(strict_types=1);
+
+namespace SimpleSAML\Test\Module\cron\Controller;
+
+use PHPUnit\Framework\TestCase;
+use SimpleSAML\Configuration;
+//use SimpleSAML\HTTP\RunnableResponse;
+use SimpleSAML\Module\cron\Controller;
+use SimpleSAML\Session;
+use SimpleSAML\Utils;
+use SimpleSAML\XHTML\Template;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Set of tests for the controllers in the "cron" module.
+ *
+ * @package SimpleSAML\Test
+ */
+class CronTest extends TestCase
+{
+    /** @var \SimpleSAML\Configuration */
+    protected $config;
+
+    /** @var \SimpleSAML\Session */
+    protected $session;
+
+    /** @var \SimpleSAML\Utils\Auth */
+    protected $authUtils;
+
+
+    /**
+     * Set up for each test.
+     * @return void
+     */
+    protected function setUp(): void
+    {
+        parent::setUp();
+
+        $this->config = Configuration::loadFromArray(
+            [
+                'module.enable' => ['cron' => true],
+                'secretsalt' => 'defaultsecretsalt'
+            ],
+            '[ARRAY]',
+            'simplesaml'
+        );
+
+        $this->session = Session::getSessionFromRequest();
+
+        $this->authUtils = new class () extends Utils\Auth {
+            public static function requireAdmin(): void
+            {
+                // stub
+            }
+        };
+
+
+        Configuration::setPreLoadedConfig(
+            Configuration::loadFromArray(
+                [
+                    'key' => 'secret',
+                    'allowed_tags' => ['daily'],
+                    'sendemail' => false,
+                ],
+                '[ARRAY]',
+                'simplesaml'
+            ),
+            'module_cron.php',
+            'simplesaml'
+        );
+    }
+
+
+    /**
+     * @return void
+     */
+    public function testInfo(): void
+    {
+        $_SERVER['REQUEST_URI'] = '/module.php/cron/info';
+        $request = Request::create(
+            '/info',
+            'GET'
+        );
+
+        $c = new Controller\Cron($this->config, $this->session);
+        $c->setAuthUtils($this->authUtils);
+        $response = $c->info($request);
+
+        $this->assertTrue($response->isSuccessful());
+    }
+
+
+    /**
+     * @return void
+     */
+    public function testRun(): void
+    {
+        $_SERVER['REQUEST_URI'] = '/module.php/cron/run/daily/secret';
+        $request = Request::create(
+            '/run/daily/secret',
+            'GET'
+        );
+
+        $c = new Controller\Cron($this->config, $this->session);
+        $response = $c->run($request, 'daily', 'secret');
+
+        $this->assertTrue($response->isSuccessful());
+    }
+}