PHPUnit测试真实示例

问题描述

| 我已经创建了一个邮件包装器类。我知道有很多库可以发送电子邮件,但是我想学习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)来帮助我理解这一过程。 希望这个帮助:)