PHPUnit测试真实的例子

时间:2011-06-14 16:16:52

标签: php email tdd phpunit wrapper

我创建了一个mail包装类。我知道有很多库可以发送电子邮件,但我想学习TDD ...所以,我已经创建了一些测试,我有一些代码。现在我可以在构造函数上设置电子邮件地址并验证它...如果电子邮件地址错误,则会出现异常。电子邮件地址是唯一一个必填字段...我没有设置和获取,因为用户将在构造函数上设置所有电子邮件数据。

现在,我要编写发送测试。我不知道如何开始它。如果我不想有定位器和吸气剂,我怎么能测试值是否存在(主题,邮件正文,标题)?我如何测试是否可以发送电子邮件?

现实世界的TDD示例对我来说很难。我试图了解它,我已经阅读了很多东西,但我无法测试真实的代码。

感谢。

3 个答案:

答案 0 :(得分:16)

由于您链接到邮件功能,因此对mail的调用很可能会硬编码到您的代码中。所以看看

安装testhelper extension并模拟对mail的调用。然后让模拟验证在调用包装器的send方法时,使用正确的值调用它,例如在某处定义自定义邮件功能:

function mail_mock()
{
    $allThatWasPassedToTheFunction = func_get_args();
    return $allThatWasPassedToTheFunction;
}

然后在send()测试中,执行类似

的操作
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]);
}

请注意,以上假设您的发送功能将返回mail()来电的结果。

通常,您将始终尝试替换外部子系统,如sendmail或数据库或具有Mock or a Stub的文件系统,因此您可以专注于独立于外部子系统测试您自己的代码。你不需要测试mail实际上是否有效。

另见http://www.phpunit.de/manual/3.6/en/test-doubles.html

答案 1 :(得分:2)

在纯单元测试中,您并未真正测试是否已发送真实电子邮件,而是是否已调用相应的编程单元(本例中为mail函数)。我真的不知道如何测试mail函数是否真的有效,因为我没有深入了解电子邮件如何工作。所以,我只想写一下如何进行单元测试。

您可以让您的类构造函数接受一个可选参数,该函数可以完成实际发送电子邮件的实际工作。默认情况下,它将是mail函数,但在您的测试设置中,您将提供实际检查正确主题,正文和标题的特殊函数。

测试:

<?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, $body, $headers, and then...

    call_user_func_array($this->mailFunction, array(
      $subject,
      $body,
      $headers
    ));
  }
}

这是某种伪代码,因为我已经为你完成或实现了一些值。重点是你应该为你正在测试的类的合作者提供测试双打。

在这种情况下,它只是一个函数(我已经使用了一些PHP 5.3)的功能,但它可能是一个你传递给被测试类的对象实例。

答案 2 :(得分:0)

我认为该课程应该对电子邮件,主题和其他信息进行验证,因此我建议将其分为函数。

当您拥有必须返回特定结果的私有验证函数时,您可以编写断言来测试它。

this article可能有用。

我对TDD也很陌生,我选择依赖IDE(Netbeans)来帮助我理解这个过程。

希望这有帮助:)