问题描述
|
我已经创建了一个邮件包装器类。我知道有很多库可以发送电子邮件,但是我想学习TDD ...因此,我已经创建了一些测试,并且我有一些代码。现在,我可以在构造函数上设置电子邮件地址并对其进行验证...如果电子邮件地址错误,则会引发异常。电子邮件地址是唯一必填字段...我没有设置和获取,因为用户将在构造函数上设置所有电子邮件数据。
现在,我要编写发送测试。我不知道如何开始。如果我不想使用setter和getter,该如何测试值是否存在(主题,邮件正文,标头)?如何测试是否可以发送电子邮件?
现实世界中的TDD示例对我来说很难。我已经尝试学习它,阅读了很多东西,但是我无法测试真实的代码。
谢谢。
解决方法
由于您已链接到邮件功能,因此对“ 0”的调用可能已硬编码到您的代码中。所以看看
http://sebastian-bergmann.de/archives/885-Stubbing-Hard-Coded-Dependencies.html
安装testhelper扩展并模拟对“ 0”的调用。然后,在调用包装器的send方法时,让模拟程序验证是否使用正确的值调用了它,例如在某处定义自定义邮件功能:
function mail_mock()
{
$allThatWasPassedToTheFunction = func_get_args();
return $allThatWasPassedToTheFunction;
}
然后在您的“ 3”测试中,执行类似
public function testSendReceivesExpectedValues()
{
// replace hardcoded call to mail() with mock function
rename_function(\'mail\',\'mail_orig\');
rename_function(\'mail_mock\',\'mail\');
// use the wrapper
$testClass = new MailWrapper(\'foo@example.com\');
$results = $testClass->send();
// assert the result
$this->assertSame(\'foo@example.com\',$results[0]);
$this->assertSame(\'Default Title\',$results[1]);
$this->assertSame(\'Default Message\',$results[2]);
}
请注意,以上假设您的send函数将返回mail()
调用的结果。
通常,您将始终尝试使用Mock或Stub替代外部子系统,例如sendmail或数据库或文件系统,因此您可以专注于测试自己的代码,以隔离外部子系统。您无需测试mail
是否有效。
另请参见http://www.phpunit.de/manual/3.6/en/test-doubles.html
, 在纯单元测试中,您实际上并没有测试是否已经发送了真实的电子邮件,而是测试了是否已调用了适当的编程单元(在这种情况下为“ 0”功能)。我真的不知道如何测试mail
函数是否真正起作用,因为我不了解电子邮件的幕后工作原理。因此,我将只写如何进行单元测试。
您可以让您的类构造函数接受一个可选参数,该函数完成实际发送电子邮件的实际工作。默认情况下,它将是“ 0”功能,但是在您的测试设置中,您将提供特殊功能,该功能实际上将检查是否存在正确的主题,正文和标题。
考试:
<?php
class EmailerTest extends PHPUnit_Framework_TestCase
{
public function testMailFunctionIsCalledWithCorrectArguments()
{
$actualSubject,$actualBody,$actualHeaders;
$mailFunction = function ($subject,$body,$headers)
use (&$actualSubject,&$actualBody,&$actualHeaders) {
$actualSubject = $subject;
$actualBody = $body;
$actualHeaders = $headers;
};
$emailer = new Emailer($options,$mailFunction);
$emailer->send();
$this->assertEquals(\'Expected subject\',$actualSubject);
$this->assertEquals(\'Expected body\',$actualBody);
$this->assertEquals(\'Expected headers\',$actualHeaders);
}
}
和正在测试的课程:
<?php
class Emailer
{
public function __construct($options,$mailFunction = \'mail\')
{
$this->subject = $options->subject;
$this->body = $options->body;
// etc.
$this->mailFunction = $mailFunction;
}
public function send()
{
// find out $subject,$headers,and then...
call_user_func_array($this->mailFunction,array(
$subject,$headers
));
}
}
这是某种伪代码,因为我留下了一些要完成或实现的值。要点是,您应该为正在测试的班级的协作者提供双打考试。
在这种情况下,它只是一个函数(我已经使用了一些PHP 5.3)功能,但是它可能是要传递给被测类的对象实例。
, 我认为该类应该对电子邮件,主题和其他信息进行验证,因此我建议将其与功能分开。
当您拥有必须返回特定结果的私有验证功能时,可以编写断言来对其进行测试。
本文可能有用。
我对TDD也很陌生,我选择依赖IDE(Netbeans)来帮助我理解这一过程。
希望这个帮助:)