From 6e8edc5af09136feab9ce5e3518bc2bee7b83902 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 14 Aug 2013 16:40:16 +0100 Subject: [PATCH] MDL-41196 Unit Tests: Add a phpmailer message sink --- lib/phpmailer/moodle_phpmailer.php | 15 ++++ lib/phpunit/classes/advanced_testcase.php | 13 ++++ lib/phpunit/classes/phpmailer_sink.php | 87 +++++++++++++++++++++++ lib/phpunit/classes/util.php | 55 ++++++++++++++ lib/phpunit/lib.php | 1 + 5 files changed, 171 insertions(+) create mode 100644 lib/phpunit/classes/phpmailer_sink.php diff --git a/lib/phpmailer/moodle_phpmailer.php b/lib/phpmailer/moodle_phpmailer.php index 03d88eeb46c..d386ab6c67c 100644 --- a/lib/phpmailer/moodle_phpmailer.php +++ b/lib/phpmailer/moodle_phpmailer.php @@ -125,4 +125,19 @@ class moodle_phpmailer extends PHPMailer { fclose($fp); return $out; } + + protected function PostSend() { + // Now ask phpunit if it wants to catch this message. + if (phpunit_util::is_redirecting_messages()) { + $mail = new stdClass(); + $mail->header = $this->MIMEHeader; + $mail->body = $this->MIMEBody; + $mail->subject = $this->Subject; + $mail->from = $this->From; + phpunit_util::phpmailer_sent($mail); + return true; + } else { + return parent::PostSend(); + } + } } diff --git a/lib/phpunit/classes/advanced_testcase.php b/lib/phpunit/classes/advanced_testcase.php index c04d3399cde..30c8d36519e 100644 --- a/lib/phpunit/classes/advanced_testcase.php +++ b/lib/phpunit/classes/advanced_testcase.php @@ -319,6 +319,19 @@ abstract class advanced_testcase extends PHPUnit_Framework_TestCase { return phpunit_util::start_message_redirection(); } + /** + * Starts email redirection. + * + * You can verify if email were sent or not by inspecting the email + * array in the returned phpmailer sink instance. The redirection + * can be stopped by calling $sink->close(); + * + * @return phpunit_message_sink + */ + public function redirectEmails() { + return phpunit_util::start_phpmailer_redirection(); + } + /** * Cleanup after all tests are executed. * diff --git a/lib/phpunit/classes/phpmailer_sink.php b/lib/phpunit/classes/phpmailer_sink.php new file mode 100644 index 00000000000..bb00478144e --- /dev/null +++ b/lib/phpunit/classes/phpmailer_sink.php @@ -0,0 +1,87 @@ +. + +/** + * phpmailer message sink. + * + * @package core + * @category phpunit + * @copyright 2013 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +/** + * phpmailer message sink. + * + * @package core + * @category phpunit + * @copyright 2013 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class phpunit_phpmailer_sink { + /** + * @var array of records which would have been sent by phpmailer. + */ + protected $messages = array(); + + /** + * Stop message redirection. + * + * Use if you do not want message redirected any more. + */ + public function close() { + phpunit_util::stop_phpmailer_redirection(); + } + + /** + * To be called from phpunit_util only! + * + * @param stdClass $message record from message_read table + */ + public function add_message($message) { + /* Number messages from 0. */ + $this->messages[] = $message; + } + + /** + * Returns all redirected messages. + * + * The instances are records form the message_read table. + * The array indexes are numbered from 0 and the order is matching + * the creation of events. + * + * @return array + */ + public function get_messages() { + return $this->messages; + } + + /** + * Return number of messages redirected to this sink. + * @return int + */ + public function count() { + return count($this->messages); + } + + /** + * Removes all previously stored messages. + */ + public function clear() { + $this->messages = array(); + } +} diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index 85cdaed9278..56b85843e3e 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -43,6 +43,9 @@ class phpunit_util extends testing_util { /** @var phpunit_message_sink alternative target for moodle messaging */ protected static $messagesink = null; + /** @var phpunit_phpmailer_sink alternative target for phpmailer messaging */ + protected static $phpmailersink = null; + /** * @var array Files to skip when resetting dataroot folder */ @@ -95,6 +98,9 @@ class phpunit_util extends testing_util { // Stop any message redirection. phpunit_util::stop_message_redirection(); + // Stop any message redirection. + phpunit_util::stop_phpmailer_redirection(); + // Release memory and indirectly call destroy() methods to release resource handles, etc. gc_collect_cycles(); @@ -660,4 +666,53 @@ class phpunit_util extends testing_util { self::$messagesink->add_message($message); } } + + /** + * Start phpmailer redirection. + * + * Note: Do not call directly from tests, + * use $sink = $this->redirectEmails() instead. + * + * @return phpunit_phpmailer_sink + */ + public static function start_phpmailer_redirection() { + if (self::$phpmailersink) { + self::stop_phpmailer_redirection(); + } + self::$phpmailersink = new phpunit_phpmailer_sink(); + return self::$phpmailersink; + } + + /** + * End phpmailer redirection. + * + * Note: Do not call directly from tests, + * use $sink->close() instead. + */ + public static function stop_phpmailer_redirection() { + self::$phpmailersink = null; + } + + /** + * Are messages for phpmailer redirected to some sink? + * + * Note: to be called from moodle_phpmailer.php only! + * + * @return bool + */ + public static function is_redirecting_phpmailer() { + return !empty(self::$phpmailersink); + } + + /** + * To be called from messagelib.php only! + * + * @param stdClass $message record from message_read table + * @return bool true means send message, false means message "sent" to sink. + */ + public static function phpmailer_sent($message) { + if (self::$phpmailersink) { + self::$phpmailersink->add_message($message); + } + } } diff --git a/lib/phpunit/lib.php b/lib/phpunit/lib.php index 2ceaf3e9860..7b0a3600b45 100644 --- a/lib/phpunit/lib.php +++ b/lib/phpunit/lib.php @@ -30,6 +30,7 @@ require_once('PHPUnit/Extensions/Database/Autoload.php'); require_once(__DIR__.'/classes/util.php'); require_once(__DIR__.'/classes/message_sink.php'); +require_once(__DIR__.'/classes/phpmailer_sink.php'); require_once(__DIR__.'/classes/basic_testcase.php'); require_once(__DIR__.'/classes/database_driver_testcase.php'); require_once(__DIR__.'/classes/arraydataset.php');