Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/289.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHPUnit中模拟对象的含义是什么?_Php_Unit Testing_Mocking_Phpunit - Fatal编程技术网

PHPUnit中模拟对象的含义是什么?

PHPUnit中模拟对象的含义是什么?,php,unit-testing,mocking,phpunit,Php,Unit Testing,Mocking,Phpunit,我正在开发一个实习生应用程序,可以通过查看方法发送一些电子邮件。现在我正在重建这个应用程序的TDD风格,但我在某个点上卡住了。我在网上搜索如何使用PHPUnit测试电子邮件,解决方案是使用模拟对象。我阅读了一些关于它的文章和教程,并用模拟对象构建了一个测试 测试通过了,但我不明白如果您已经知道结果,为什么要使用模拟对象。我的意思是,如果你已经知道结果,你就看不到你真正方法的失败?那么,这不是测试使用电子邮件功能的方法吗?还是我只是做错了?可能是第二个哈哈 提前感谢, Sjors使用模拟对象的原因

我正在开发一个实习生应用程序,可以通过查看方法发送一些电子邮件。现在我正在重建这个应用程序的TDD风格,但我在某个点上卡住了。我在网上搜索如何使用PHPUnit测试电子邮件,解决方案是使用模拟对象。我阅读了一些关于它的文章和教程,并用模拟对象构建了一个测试

测试通过了,但我不明白如果您已经知道结果,为什么要使用模拟对象。我的意思是,如果你已经知道结果,你就看不到你真正方法的失败?那么,这不是测试使用电子邮件功能的方法吗?还是我只是做错了?可能是第二个哈哈

提前感谢,


Sjors

使用模拟对象的原因是隔离。如果您编写单元测试,您希望它们尽可能与其他系统或代码隔离。因此命名为单元测试。使用mock允许您将测试与其他系统隔离(在您的情况下,使用电子邮件)。Misko Hevery的一篇演讲比我以往任何时候都能更好地解释这一方面。

当您进行单元测试时,您应该尝试与系统的其他部分隔离地测试您的测试方法(测试中的工作单元)。一旦您被迫跨越系统边界,您的单元测试就变成了集成测试。集成测试往往更脆弱、更难编写和维护。通过将邮件组件与创建邮件的方法隔离,您不再需要在单元测试运行时依赖邮件系统是否已启动和运行。您可以自由地测试被测试方法中的逻辑,而不必依赖于具体的实现

有两类模拟测试,交互测试和基于状态的测试。我建议在谷歌上查找两者之间的差异

不幸的是,我不熟悉php的语法,我只能向您展示一个使用C#语法在您的案例中测试的示例,但我相信您将能够遵循代码

public interface Mailer
{
  void Send(string to, string from, string subject, string body)
}
上面的接口将与实际发送邮件的邮件组件的签名相匹配(它知道smtp等)

现在我们在GenerateEmail方法中有了逻辑。您可以编写单元测试来检查是否存在无效电子邮件地址和空主题的异常,还可以编写单元测试来确保如果您有有效的电子邮件地址和不为空的主题,则会使用每个参数中的正确信息对模拟邮件发件人调用send方法。这种类型的单元测试将是一种交互测试,因为模拟只是验证方法是否被调用)


希望这个解释有帮助。

您不应该测试模拟对象;您可以使用模拟对象替换由您正在测试的类引用的依赖对象,以使测试独立于那些其他类。其他每个类都应该有自己的单元测试来测试它们的功能啊,我误解了模拟对象的防御!我现在将模拟对象作为依赖项发送到控制器(我使用MVC模式)。谢谢你们的快速回复,伙计们!
public class MailSender
{
  private IMailer _mailer;
  public MailSender(IMailer mailer)
  {
    _mailer = mailer;
  }

  public void GenerateMail(string to, string cc, string from, string subject, string body)
  {
    if (IsValidEmailAddress(to) == false) throw new InvalidEmailAddressException("To"); 
    if (IsEmptySubject(from) == false) throw new EmptySubjectException();    
    _mailer.Send(to, from, subject, body);
  }

  private bool IsValidEmailAddress(string emailAddress)
  {
    // some code/regex to check that the email address is valid
  }

  private boold IsEmptySubject(string subject)
  {
    // code to check if the subject is empty
  }
}