php PHPUnit 测试真实示例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6346690/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:06:04  来源:igfitidea点击:

PHPUnit tests real example

phpemailtddphpunitwrapper

提问by thom

I've created a mailwrapper 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.

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

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?

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

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.

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

Thanks.

谢谢。

采纳答案by Gordon

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

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

Install the testhelper extensionand 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:

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

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

Then in your send()test, do something like

然后在你的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]);
}

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

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

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 mailactually works.

通常,您总是会尝试用Mock 或 Stub替换外部子系统,例如 sendmail 或数据库或文件系统,因此您可以专注于测试自己的代码,与外部子系统隔离。您不需要测试mail实际有效。

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

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

回答by Ionu? G. Stan

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 mailfunction in this case) has been called. I don't really know how to test whether the mailfunction 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.

在纯单元测试中,您不会真正测试是否发送了真实的电子邮件,而是测试是否mail调用了适当的编程单元(在本例中为函数)。我真的不知道如何测试该mail功能是否真的有效,因为我对电子邮件的工作原理没有深入了解。所以,我只会写下我将如何进行单元测试。

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 mailfunction, but in your test setup, you provide your special function that will actually checks the correct subject, body and headers are present.

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

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.

在这种情况下,它只是一个函数(我使用了一些 PHP 5.3)特性,但它可能是一个对象实例,您将传递给被测类。

回答by Panuwizzle

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 articlemight be useful.

这篇文章可能有用。

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

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

hope this help :)

希望这有帮助:)