PHPUnit测试真实例子

发布于 2024-11-15 04:24:32 字数 383 浏览 3 评论 0原文

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

现在,我要编写发送测试。我不知道如何开始。如果我不想有 setter 和 getter,我该如何测试这些值是否存在(主题、邮件正文、标题)?如何测试是否可以发送电子邮件?

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

谢谢。

I've created a mail wrapper class. I know that there are lots of libraries to send e-mails but i want to learn TDD... So, I've created some tests and i have some code. Now I can set the email address on constructor and validate it... if the email address is wrong, an exception raise up. The email address is the only one required field... I don't have sets and gets because user will setup all email data on constructor.

Now, i'm going to write the send tests. I don't know how to start it. How could i test if the values are there (subject, mail body, headers) if i don't want to have setters and getters? How could I test if an email could be sent?

Real world TDD examples are hard to me. I've tried to learn about it, i've read lots of things but i cannot test real code.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌生 2024-11-22 04:24:32

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

安装 testhelper 扩展 并模拟调用邮件。然后让模拟验证当调用包装器的发送方法时它是否使用正确的值进行调用,例如在某处定义自定义邮件函数:

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('[email protected]');
    $results = $testClass->send();

    // assert the result
    $this->assertSame('[email protected]', $results[0]);
    $this->assertSame('Default Title', $results[1]);
    $this->assertSame('Default Message', $results[2]);
}

注意上面假设您的发送函数将返回 mail() 调用的结果。

一般来说,您总是会尝试使用 Mock 或存根,这样您就可以专注于测试自己的代码,而与外部子系统隔离。您不需要测试mail是否确实有效。

另请参阅http://www.phpunit.de/manual/3.6/en/test-doubles。 html

Since you linked to the mail function, the call to mail is likely hardcoded into your code. So have a look at

Install the testhelper extension and mock the call to mail. Then have the mock validate that it got called with the correct values when your wrapper's send method is called, e.g. define a custom mail function somewhere:

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

Then in your send() test, do something like

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('[email protected]');
    $results = $testClass->send();

    // assert the result
    $this->assertSame('[email protected]', $results[0]);
    $this->assertSame('Default Title', $results[1]);
    $this->assertSame('Default Message', $results[2]);
}

Note that the above assumes your send function will return the result of the mail() call.

In general, you will always try to substitute an external subsystem, like sendmail or a database or the filesystem with a Mock or a Stub, so you can concentrate on testing your own code in isolation of the external subsystem. You dont need to test that mail actually works.

Also see http://www.phpunit.de/manual/3.6/en/test-doubles.html

酷到爆炸 2024-11-22 04:24:32

在纯单元测试中,您并不真正测试是否已发送真实的电子邮件,而是测试是否已调用适当的编程单元(在本例中为 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)功能,但它可能是您传递给测试类的对象实例。

In a pure unit test, you don't really test whether a real email has been sent, but rather whether the appropriate programming unit (the mail function in this case) has been called. I don't really know how to test whether the mail function really works as I don't have in depth knowledge of how emailing works under the hood. So, I'll just write how I'd do the unit test.

You can have your class constructor accept an optional argument, a function that does the real work of actually sending the email. By default, it will be the mail function, but in your test setup, you provide your special function that will actually checks the correct subject, body and headers are present.

The test:

<?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);
  }
}

And the class under test:

<?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
    ));
  }
}

It's some sort of pseudo-code, because I've left some of the values for you to complete or implement. The main point is that you should supply test doubles for the collaborators of the class you're testing.

In this case it's just a function (I've made use of some PHP 5.3) features, but it could be an object instance that you'd pass to the class under test.

我很坚强 2024-11-22 04:24:32

我认为该类应该对电子邮件、主题和其他信息进行验证,因此我建议这应该与函数分开。

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

这篇文章可能有用。

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

希望这有帮助:)

I think the class should performs validation for email, subject and other information so I suggest this should be separated to the functions.

When you have the private validation function that must return specific result then you can write the assertion to test it.

this article might be useful.

I'm very new to TDD too and I choose to depend on the IDE (Netbeans) to help me understand this process.

hope this help :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文