Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Add Email Logger for JLog #1168

Closed
wants to merge 1 commit into from

2 participants

@AmyStephen

I did a little reading on testing email capabilities and found recommendations to use a mocked class to simulate the email function. I noticed that JLoggerMessageQueueTest mocks up JApplication, so I used that approach as a guide.

For the most part, the testing worked perfectly, except I am unable to retrieve the mock class properties from the test in a similar manner to how the application mock object is referenced.

What I ended up doing (which I do not recommend be a permanent change), but I changed the Logger Mail class to be public so that I could do the comparisons using that approach.

Would appreciate feedback on what I should be doing to use the Mock class properties.

Also, these are essentially my first Unit tests, so any direction is appreciated.

@LouisLandry

Don't have time to do anything thorough on this with you right now, but instead of making it public you just need to use reflection. We've added a helper to make that easy for you in the test classes.

<?php

// Invoke a non-public method.
$result = TestReflection::invoke($object, 'methodName', $arg1, $arg2);

// Get a non-public member.
$value = TestReflection::getValue($object, 'memberName');

// Set a non-public member.
TestReflection::setValue($object, 'memberName', $valueToSet);

That helper makes it much easier to test non-public aspects of your classes. You are on the right track with mocking out the mailer, though I don't think you need to put that much effort into it. You really just need a mock object that will validate the methods that are called, More along the lines of our TestMock* classes. You'll find that stuff in https://github.com/joomla/joomla-platform/tree/staging/tests/core.

@AmyStephen

Perfect, very helpful. TestReflection::getValue was just what I needed.

My mock class is only those methods called. The only "fancy" thing I did was set an array of values but that was because I didn't want to create a test method for each value. Otherwise, that mock class is nothing fancy.

Appreciate your time. I think this ready for consideration.

@AmyStephen

Since it's been over two months, I'm going to close this.

@AmyStephen AmyStephen closed this
@LouisLandry

Please open it again. I think given the autoloader changes that Rouven made we may need to adjust a couple of things, but it is just as relevant ... just hasn't been on the top of my list to deal with recently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 22, 2012
  1. Add Email Logger for JLog

    Amy Stephen authored
This page is out of date. Refresh to see the latest.
View
39 docs/manual/en-US/chapters/packages/log.xml
@@ -14,7 +14,7 @@
formats.</para>
<para>The classes included in the Log package are JLog, JLogEntry, LogException, JLogger as well as the classes
- JLoggerDatabase, JLoggerEcho, JLoggerFormattedText, JLoggerMessageQueue, JLoggerSyslog and JLoggerW3C which support formatting
+ JLoggerDatabase, JLoggerEcho, JLoggerEmail, JLoggerFormattedtext, JLoggerMessagequeue, JLoggerSyslog and JLoggerW3c which support formatting
and storage. Of all these classes, you will generally only use JLog in your projects.</para>
<para>Logging is a two-step process.</para>
@@ -271,7 +271,7 @@ JLog::addLogger(
JLog::addLogger(
array(
'text_file' =&gt; 'com_hello.php',
- 'text_entry_format' =&gt; '{DATE} {TIME} {CLIENTIP} {CATEGORY} {MESSAGE}'
+ 'text_entry_format' =&gt; '{DATE} {TIME} {CLIENTIP} {CATEGORY} {MESSAGE}'
)
);</programlisting>
</example>
@@ -288,7 +288,7 @@ JLog::addLogger(
JLog::addLogger(
array(
'text_file' =&gt; 'com_shop.sales.php',
- 'text_entry_format' =&gt; '{DATETIME} {PRICE} {QUANTITY} {MESSAGE}'
+ 'text_entry_format' =&gt; '{DATETIME} {PRICE} {QUANTITY} {MESSAGE}'
),
JLog::INFO,
'Shop'
@@ -366,4 +366,37 @@ JLog::add(json_encode($log), JLog::INFO, 'dblog');</programlisting>
<para>This makes it possible to retrieve detailed information for display.</para>
</section>
+
+ <section>
+ <title>Logging to email</title>
+
+ <para>The "email" logger allows you to send a log message via email. </para>
+
+ <para>To log messages using the "email" logger, you the following code as a guide.</para>
+
+ <example>
+ <title>Using an email logger</title>
+
+ <programlisting>// Add the logger.
+ JLog::addLogger(
+ array(
+ 'logger' =&gt; 'email',
+ 'from' =&gt; 'admin@example.com',
+ 'to' =&gt; 'support@example.com'
+ ),
+ JLog::EMERGENCY,
+ 'Alert'
+ );
+
+ // Add the message.
+ JLog::add('Database Connection Failed.', JLog::EMERGENCY, 'alert');</programlisting>
+ </example>
+
+ <para>Notice that the example binds the logger to the emergency message priority for a category of "alert".</para>
+
+ <para>The mail logger works with JMail. For the Joomla CMS, if the "from" and "to" values are omitted
+ from the addLogger call, JLog will retrieve the configuration "mailfrom" value and use it for both parameters.</para>
+ </section>
+
+
</section>
View
119 libraries/joomla/log/loggers/email.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * @package Joomla.Platform
+ * @subpackage Log
+ *
+ * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
+ * @license GNU General Public License version 2 or later; see LICENSE
+ */
+
+jimport('joomla.log.logger');
+
+defined('JPATH_PLATFORM') or die;
+
+/**
+ * Joomla Email logger class.
+ *
+ * @package Joomla.Platform
+ * @subpackage Log
+ * @since 12.1
+ */
+class JLoggerEmail extends JLogger
+{
+ /**
+ * @var string From email address
+ * @since 12.1
+ */
+ protected $from;
+
+ /**
+ * @var string To email address list
+ * @since 12.1
+ */
+ protected $to;
+
+ /**
+ * @var string Mailer Object
+ * @since 12.1
+ */
+ protected $mailer;
+
+ /**
+ * Constructor.
+ *
+ * @param array $options Log object options.
+ *
+ * @since 12.1
+ */
+ public function __construct(array $options)
+ {
+ parent::__construct($options);
+
+ if (empty($this->options['from']))
+ {
+ $this->from = JFactory::getConfig()->get('mailfrom');
+ }
+ else
+ {
+ $this->from = $this->options['from'];
+ }
+
+ if (empty($this->options['to']))
+ {
+ $this->to = JFactory::getConfig()->get('mailfrom');
+ }
+ else
+ {
+ $this->to = $this->options['to'];
+ }
+
+ if (empty($this->options['mailer']))
+ {
+ $this->mailer = JFactory::getMailer();
+ }
+ else
+ {
+ $this->mailer = $this->options['mailer'];
+ }
+ }
+
+ /**
+ * Method to email log entry.
+ *
+ * @param JLogEntry $entry The log entry object to add to the log.
+ *
+ * @return void
+ *
+ * @since 12.1
+ * @throws RuntimeException
+ */
+ public function addEntry(JLogEntry $entry)
+ {
+ $this->mailer->setSender($this->from);
+
+ $this->mailer->addRecipient($this->to);
+
+ $message = $this->priorities[$entry->priority]
+ . ': '
+ . $entry->message
+ . (empty($entry->category) ? '' : ' [' . $entry->category . ']');
+
+ if (strlen($message) > 50)
+ {
+ $this->mailer->setSubject(substr($message, 0, 50) . '...');
+ }
+ else
+ {
+ $this->mailer->setSubject(trim($message));
+ }
+
+ $this->mailer->setBody($message);
+
+ $results = $this->mailer->Send();
+
+ if ($results == false)
+ {
+ throw new RuntimeException('Email log entry not sent');
+ }
+ }
+}
View
125 tests/suites/unit/joomla/log/loggers/JLoggerEmailTest.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * @package Joomla.UnitTest
+ * @subpackage Log
+ *
+ * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
+ * @license GNU General Public License version 2 or later; see LICENSE
+ */
+
+require_once JPATH_PLATFORM.'/joomla/log/loggers/email.php';
+require_once __DIR__.'/stubs/email/mock.mail.php';
+
+/**
+ * Test class for JLoggerEmail.
+ */
+class JLoggerEmailTest extends PHPUnit_Framework_TestCase
+{
+ /**
+ * @var mixed The main mail object from JFactory while we mock it out.
+ * @since 11.1
+ */
+ protected $mailer;
+
+ /**
+ * Setup for testing.
+ *
+ * @return void
+ */
+ public function setUp()
+ {
+ $this->mailer = JFactory::$mailer;
+ JFactory::$mailer = new JMailMock();
+ }
+
+ /**
+ * Tear down.
+ *
+ * @return void
+ */
+ public function tearDown()
+ {
+ JFactory::$mailer = $this->mailer;
+ }
+
+ /**
+ * Test the JLoggerMail::addEntry method.
+ */
+ public function testSendEmail01()
+ {
+ // Create config.
+ $config = array(
+ 'categories' => 'Emergency Alerts',
+ 'priorities' => JLog::EMERGENCY,
+ 'from' => 'Person@example.com',
+ 'to' => 'Person@example.com'
+ );
+
+ // Get an instance of the email logger, passing in configuration
+ $logger = new JLoggerEmail($config);
+
+ // Add log entry
+ $logger->addEntry(new JLogEntry('Database connection failed', JLog::EMERGENCY, 'Alert'));
+
+ // Expected results
+ $expected = array(
+ 'Person@example.com',
+ NULL,
+ 'Person@example.com',
+ 'EMERGENCY: Database connection failed [alert]',
+ 'EMERGENCY: Database connection failed [alert]'
+ );
+
+ // Verify results
+ $this->assertEquals(TestReflection::getValue($logger, 'mailer')->Sent, $expected);
+ }
+
+ /**
+ * Verify a long Subject is shortened
+ */
+ public function testSendEmail02()
+ {
+ // Create config.
+ $config = array(
+ 'categories' => 'Emergency Alerts',
+ 'priorities' => JLog::EMERGENCY,
+ 'from' => 'Person@example.com',
+ 'to' => 'Person@example.com'
+ );
+
+ // Get an instance of the email logger, passing in configuration
+ $logger = new JLoggerEmail($config);
+
+ // Add log entry
+ $longMessage = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
+ $logger->addEntry(new JLogEntry($longMessage, JLog::EMERGENCY, 'Alert'));
+
+ $expected = 'EMERGENCY: Lorem Ipsum is simply dummy text of the...';
+
+ // Verify results
+ $this->assertEquals(TestReflection::getValue($logger, 'mailer')->Subject, $expected);
+ }
+
+ /**
+ * Verify email is not sent if From is not specified
+ */
+ public function testSendEmail03()
+ {
+ // Create config.
+ $config = array(
+ 'categories' => 'Emergency Alerts',
+ 'priorities' => JLog::EMERGENCY,
+ 'to' => 'Person@example.com',
+ 'from' => null
+ );
+
+ // Get an instance of the email logger, passing in configuration
+ $logger = new JLoggerEmail($config);
+
+ // Test should fail due to null value for from
+ $this->setExpectedException('RuntimeException');
+
+ // Add log entry
+ $logger->addEntry(new JLogEntry('This should fail', JLog::EMERGENCY, 'Alert'));
+ }
+}
View
148 tests/suites/unit/joomla/log/loggers/stubs/email/mock.mail.php
@@ -0,0 +1,148 @@
+<?php
+/**
+ * @package Joomla.UnitTest
+ * @subpackage Log
+ *
+ * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
+ * @license GNU General Public License version 2 or later; see LICENSE
+ */
+
+/**
+ * Inspector classes for the JLog package.
+ */
+
+/**
+ * @package Joomla.UnitTest
+ * @subpackage Log
+ */
+class JMailMock
+{
+ /**
+ * @var string From (email address)
+ * @since 12.1
+ */
+ public $From;
+
+ /**
+ * @var string FromName (Name of sender)
+ * @since 12.1
+ */
+ public $FromName;
+
+ /**
+ * @var string to
+ * @since 12.1
+ */
+ public $to;
+
+ /**
+ * @var string Subject
+ * @since 12.1
+ */
+ public $Subject;
+
+ /**
+ * @var string Body
+ * @since 12.1
+ */
+ public $Body;
+
+ /**
+ * @var array Sent
+ * @since 12.1
+ */
+ public $Sent = array();
+
+ /**
+ * Set the Sender value
+ *
+ * @param array $value
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ public function setSender($value)
+ {
+ if (is_array($value))
+ {
+ $this->From = $value[0];
+ $this->FromName = $value[1];
+ }
+ else
+ {
+ $this->From = $value;
+ }
+ }
+
+ /**
+ * Add Recipient value
+ *
+ * @param string $value
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ public function addRecipient($value)
+ {
+ $this->to = $value;
+ }
+
+ /**
+ * Set the Subject value
+ *
+ * @param string $value
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ public function setSubject($value)
+ {
+ $this->Subject = $value;
+ }
+
+ /**
+ * Set the Body value
+ *
+ * @param string $value
+ *
+ * @return void
+ *
+ * @since 12.1
+ */
+ public function setBody($value)
+ {
+ $this->Body = $value;
+ }
+
+ /**
+ * Send the email
+ *
+ * @return boolean
+ *
+ * @since 12.1
+ */
+ public function Send()
+ {
+ if ($this->From === null
+ || $this->to === null
+ || $this->Subject === null
+ || $this->Body === null)
+ {
+ return false;
+ }
+ else
+ {
+ $this->Sent = array(
+ $this->From,
+ $this->FromName,
+ $this->to,
+ $this->Subject,
+ $this->Body
+ );
+ return true;
+ }
+ }
+}
Something went wrong with that request. Please try again.