diff --git a/step/email/tests/lib_test.php b/step/email/tests/lib_test.php
new file mode 100644
index 00000000..d6a0fb39
--- /dev/null
+++ b/step/email/tests/lib_test.php
@@ -0,0 +1,58 @@
+.
+/**
+ * Unit tests for the lifecyclestep_email lib.php.
+ *
+ * @package lifecyclestep_email
+ * @copyright 2024 Justus Dieckmann, University of Münster.
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+namespace lifecyclestep_email;
+
+/**
+ * Unit tests for the lifecyclestep_email lib.php.
+ *
+ * @package lifecyclestep_email
+ * @copyright 2024 Justus Dieckmann, University of Münster.
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+final class lib_test extends \advanced_testcase {
+
+ /**
+ * Tests \tool_lifecycle\step\email::replace_placeholders.
+ *
+ * @covers \tool_lifecycle\step\email::replace_placeholders
+ */
+ public function test_replace_placeholders(): void {
+ $this->resetAfterTest();
+
+ $user1 = $this->getDataGenerator()->create_user(['firstname' => 'Jane', 'lastname' => 'Doe']);
+ $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course 1', 'shortname' => 'C1']);
+ $course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course 2', 'shortname' => 'C2']);
+ $lib = new \tool_lifecycle\step\email();
+ $callReplacePlaceholders = function($strings, $user, $stepid, $mailentries) {
+ return $this->replace_placeholders($strings, $user, $stepid, $mailentries);
+ };
+ $response = $callReplacePlaceholders->call($lib, [
+ "##firstname##\n##lastname##\n##courses##\n##shortcourses##",
+ "##firstname##
##lastname##
##courses-html##
##shortcourses-html##"
+ ], $user1, 0, [(object) ['courseid' => $course1->id], (object) ['courseid' => $course2->id]]);
+
+ $this->assertCount(2, $response);
+ $this->assertEquals("Jane\nDoe\nCourse 1\nCourse 2\nC1\nC2", $response[0]);
+ $this->assertEquals("Jane
Doe
Course 1
Course 2
C1
C2", $response[1]);
+ }
+}