Mock Objects

Mock Objects

Sometimes during testing you need to interact with a deterministic object that for various reasons you do not have access to in your testing environment. For instance:

  • The real object is nondeterministic, such as a real-time stock or weather-feed.

  • The real object is too slow for your test suites, such as an overloaded transactional production database.

  • You need to test exceptional situations, such as an intrusion alarm or systems outage.

  • The real object does not exist. This can be anything from not having access to the required object to required intra-object functionality.

Essentially, a mock object is an object that feigns enough functionality or required functionality for you to fully test your system.

For instance, if you wanted to test for session timeouts, errors, or just malicious cracking you might import mock-widgetsession.phpm, which consists of:

   class MockWidgetSession extends WidgetSession {        public function getUserObject() {            return new WidgetUser(                array (                    'id' => 1,                    'username' => 'ed',                    'md5_pw' => "827ccb0eea8a706c4c34a16891f84e7b",                    'first_name' => "Ed",                    'last_name' => "Lecky-Thompson",                    'email' => "",                    'role' => "s",                    'department' => "sales"));        }    } 

Coding details aside, this MockWidgetSession example would allow your testing environment to simulate a login for whatever reason you require.

Smarty can also be used to mock up HTML screens. Other than displaying the HTML to the screen, you can save the HTML in a variable and do with it as you please.

For instance, Story 6 requires sales manager notification, so you merely need to send an e-mail to the managers when the contacts are saved. Sounds pretty simple, but you're faced with an issue of how intensively you'd like to test, especially since they'd like the content of the e-mail to include the HTML from the input screen.

Getting the screen HTML is not an issue. Essentially, you need to test the browser output, which is nice because up until now, you haven't been testing what the browser sees. For end-to-end completeness, the following test will reference the HTML output using a regular expression.

         function testContactEmail () {              $u = new WidgetUser(                  array ('id'         => 1,                         'username'   => "ed",                         'first_name' => "Ed",                         'last_name'  => "Lecky-Thompson",                         'email'      => "",                         'role'       => "s",                         'department' => "sales"));              $cv = new ContactVisit (                  array ('emp_id'             => "1",                         'week_start'         => "1980-01-01",                         'company_name'       => "test one",                         'contact_name'       => "Big One",                         'city'               => "Columbus",                         'state'              => "OH",                         'accomplishments'    => "phone call",                         'followup'           => "",                         'literature_request' => ""));              $c = new Contact (                  array ("emp_id"             => "1",                         "week_start"         => "1980-01-01",                         "shop_calls"         => 2,                         "distributor_calls"  => 3,                         "engineer_calls"     => 4,                         "mileage"            => 50,                         "territory_worked"   => "Central Ohio",                         "territory_comments" => "Buckeyes are great."),                  $this->_session->getDatabaseHandle());              list ($email,_$from, $subject, $message, $headers) =                  generateContactEmail($u, $c, array ($cv), false);              // test screen capture, requires 7bit ascii encoding (read: none)              $this->assertEquals(1, preg_match ("/Employee Name..............Ed     Lecky-Thompson/", $message), "employee name");              $this->assertEquals(1, preg_match     ("/company_name_0........................................test one/",    $message), "company name");             $this->assertEquals(1, preg_match     ("/shop_calls.................................2/", $message),"shop calls");             $this->assertEquals(1, preg_match ("/To:",     $headers),"email");             // test base64 encoding             list ($email_from, $subject, $message, $headers) =                 generateContactEmail($u, $c, array ($cv));             $this->assertEquals(0, preg_match ("/Employee Name..............Ed    Lecky-Thompson/", $message), "employee name");             $this->assertEquals(1, preg_match ("/To:",     $headers),"email");         } 

The generateContactEmail() function is designed to return what is required by the PHP mail() function: mail($email_address, $subject, $message, $headers);.

Also note that in this example you're testing what the browser sees. Instead of testing 100 percent of the HTML output, you're making sure that the form contains the information you expect. Thus, the simple regular expression of:

   "/Employee Name..............Ed Lecky-Thompson/" 

will perfectly match the generated HTML of:

   <tr><td><b>Employee Name:</b></td><td>Ed Lecky-Thompson</td>    <td><b>Department:</b></td><td>sales</td></tr> 

Also note that because the base64 encoding is unreadable by humans, the tests of base64 encoding check only for the existence of the e-mail address in the e-mail header, and not the Employee Name because Employee Name, being in the message and base64 encoded, can't be normally read.

Here are the functions that might be placed in your lib/common-functions.phpm:

   function mimeifyContent ($content, $mime_boundary,                             $filename, $flagBase64=true) {        $message = "";        $message .= " \r\n";        $message .= "--".$mime_boundary."\r\n";        $message .= "Content-Type: text/html;\r\n";        $message .= " name=\"".$filename.".html\"\r\n";        // default is 7bit ascii        if ($flagBase64) {            $message .= "Content-Transfer-Encoding: base64\r\n";        }        $message .= "Content-Disposition: attachment;\r\n";        $message .= " filename=\"".$filename.".html\"\r\n";        $message .= "\r\n";        if ($flagBase64) {            $message .= base64_encode($content);        } else {            $message .= $content;        }        $message .= "\r\n";        return ($message);    }    function generateContactEmail (&$user, &$contact,                                   $contactVisits, $flagBase64=true) {        global $GLOBALS;        require_once ($GLOBALS["smarty-path"].'Smarty.class.php');        $smarty = new Smarty;        $smarty->assign_by_ref ("user", $user);        $smarty->assign_by_ref ("contact", $contact);        $smarty->assign_by_ref ("contactVisits", $contactVisits);        $smarty->assign('start_weeks', getStartWeeks());        $smarty->assign('current_start_week', $contact->week_start);        $smarty->assign("max_weekly_contacts", $GLOBALS["max-weekly-contacts"]);        $email_body = @$smarty->fetch('customer-contacts.tpl');        $headers = "";        $headers .= "From: ".$GLOBALS["email-from"]."\n";        $headers .= "To: ".$user->email."\n";        if (strlen ($GLOBALS["email-contact-cc"]) > 0)            $headers .= "Cc: ";            $headers .= $GLOBALS["email-contact-cc"];        $headers .= "\n";        if (strlen ($GLOBALS["email-contact-bcc"]) > 0)            $headers .= "Bcc: ".$GLOBALS["email-contact-bcc"]."\n";        $mime_boundary = "<<<--==+X[".md5(time())."]";        $headers .= "MIME-Version: 1.0\r\n";        $headers .= "Content-Type: multipart/mixed;\r\n";        $headers .= " boundary=\"".$mime_boundary."\"";        $message = "";        $message .= "This is a multi-part message in MIME format.\r\n";        $message .= "\r\n";        $message .= "--".$mime_boundary."\r\n";        $message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";        $message .= "Content-Transfer-Encoding: 7bit\r\n";        $message .= "\r\n";        $message .= $GLOBALS["email-contact-message"]."\n\n";        $nextEnding = "\r\n";        $message.=mimeifyContent($email_body,$mime_boundary,                                 "customer-contact", $flagBase64);        $message.="--".$mime_boundary."".$nextEnding;        $subject = $user->emp_id." ".$user->last_name." : ".$user->email_subject;        return array ($user->email, $subject, $message, $headers);    } 

Two things should be noted here. You're calling $smarty->fetch() instead of $smarty-> display() . The fetch function places the HTML output into a variable rather than to the screen, as does the display function.

Also, for technical reasons, it's safer to base64-encode HTML output if there is any chance of its using non-7bit ASCII, for instance, if you're using Unicode or non-English characters. However, base64 encoding the HTML in the e-mail makes it practically untestable, which is why the $flagBase64 argument exists.

If this function contained the function to physically mail the e-mail instead of simply creating the content, you'd most certainly create and utilize a mock object that simulated the e-mailing API and didn't base64 encode the content.

Professional PHP5 (Programmer to Programmer Series)
Professional PHP5 (Programmer to Programmer Series)
Year: 2003
Pages: 182
BUY ON AMAZON © 2008-2017.
If you may any questions please contact us: