在CakePHP中的单元测试期间使用不同的电子邮件配置 [英] Use a different email config during unit testing in CakePHP

查看:112
本文介绍了在CakePHP中的单元测试期间使用不同的电子邮件配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个控制器的操作中使用CakeEmail类发送电子邮件。我有一个单元测试这个控制器,在添加电子邮件代码之前工作正常。添加电子邮件后,我收到此错误:

I'm sending an email using the CakeEmail class in an action of one of my controllers. I have a unit test for this controller that was working fine before adding the email code. After adding the email I get this error:


SocketException:无法发送电子邮件。

SocketException: Could not send email.

这是因为我没有办法从我的本地计算机发送电子邮件。

This is down to the fact that I don't have any way of sending emails off my local machine.

所以我认为也许一个好主意是在ConfigConfig类中的两个不同的配置选项Config / email.php(类似于数据库配置文件的工作原理)。默认使用邮件传输,并使用Debug传输进行测试。这个问题是,与数据库配置不同,Cake在测试期间不会自动在两者之间切换。

So I thought that maybe a good idea would be to have two different configuration options inside the EmailConfig class in Config/email.php (Similar to how the database config file works). The default using the Mail transport, and a test using the Debug transport. The issue with this is that, unlike the database config, Cake doesn't automatically switch between the two during testing.

我想到的唯一的事情是添加一个构造函数到EmailConfig类并测试我们是否为单元测试,但我不知道该检查应该是什么。

The only thing I have thought of is to add a constructor to the EmailConfig class and test if we're unit testing, but I'm not sure what the check should be.

这样做的东西:

class EmailConfig {

    public $default = array(
        'transport' => 'Mail'
    );

    public $test = array(
        'transport' => 'Debug'
    );

    public function __construct() {
        if ($isUnitTesting) {
            $this->default = $this->test;
        }
    }

}

方式建议以上是一个好主意?

Would my way suggested above be a good idea? If not, what other ways can I use a different transport for the email during unit testing?

更新 - 4/10/2012

我想我这是错误的方式。看看这个答案,似乎即使 $ default config isn默认情况下,你必须通过调用 CakeEmail :: config()方法或在构造函数中指定它。所以我认为现在有两个选项:

I think I was going about this the wrong way. Looking at this answer it seems that even the $default config isn't loaded by default, you have to specify it by calling the CakeEmail::config() method or give it in the constructor. So I think this leaves me two options now:


  1. 在控制器中检查我们是否进行单元测试'test'config。

  2. 设置我的计算机以便能够发送电子邮件。

我宁愿做第一个但不确定如何做,如果没有膨胀控制器动作与检查,如果我们是单元测试,这似乎是错误的这样做。

I'd rather do the first but unsure how this can be done without bloating the controller action with checks if we're unit testing, it seems wrong to do this.

推荐答案

最简单的方法是在测试时可能切换到DebugTransport。测试的一部分是,你需要设计你的程序是可测试的。事实上,这里有一些功能和整个蛋糕设计来做到这一点。对于您的应用程序,假设您在用户注册时发送电子邮件:

The easiest way is to probably switch to the DebugTransport while testing. Part of testing is that you need to design your program to be testable. In fact, there are a few functions here and there throughout Cake designed to do just that. For your app, let's assume you send an email when a user registers:

App::uses('CakeEmail', 'Network/Email');
App::uses('AppController', 'Controller');

class UsersController extends AppController {

  public function register() {
    //registration logic
    $email = new CakeEmail();
    $email->from(array('site@example.com' => 'Site'));
    $email->to('you@example.com');
    $email->subject('Registered');
    $email->send('Thanks for registering!');
  }

}

这看起来无害,但你不能mock CakeEmail ,因为它不允许依赖注入< a>,这是测试时必需的。相反, CakeEmail 类应该以允许我们以后更改的方式实例化。例如:

This looks harmless, but you cannot mock CakeEmail because it does not allow for dependency injection, which is necessary when testing. Instead, the CakeEmail class should be instantiated in a way that allows us to change it later. For example:

App::uses('CakeEmail', 'Network/Email');
App::uses('AppController', 'Controller');

class UsersController extends AppController {

  public function register() {
    //registration logic
    $email = $this->_getEmailer();
    $email->from(array('site@example.com' => 'Site'));
    $email->to('you@example.com');
    $email->subject('Registered');
    $email->send('Thanks for registering!');
  }

  public function _getEmailer() {
    return new CakeEmail();
  }

}

因为我们添加了一个辅助函数,我们现在可以测试它(通过嘲笑助手函数)。

Because we added a little helper function, we can now test it (by mocking the helper function).

App::uses('CakeEmail', 'Network/Email');
App::uses('UsersController', 'Controller');

class UsersControllerTest extends ControllerTestCase {

  public function testRegister() {
    $controller = $this->generate('Users', array(
      'methods' => array(
        '_getEmailer'
      )
    ));
    $emailer = new CakeEmail();
    $emailer->transport('Debug');
    $controller
      ->expects($this->any())
      ->method('_getEmailer')
      ->will($this->returnValue($emailer));
  }

}

此测试创建一个mock对象当调用 _getEmailer 方法时,我们的控制器并告诉它返回我们新创建的 $ emailer 由于 $ emailer 已将传输设置为调试,因此可以安全地进行测试。

This test creates a mock object for our controller and tells it to return our newly created $emailer object when the _getEmailer method is called. Since $emailer has set the transport to 'Debug', it's safe for testing.

我们决定该方法返回什么电子邮件对象,嘲笑 CakeEmail 对象,并期望某些返回变得微不足道。

Of course, since now we're deciding what email object the method returns, mocking the CakeEmail object and expecting certain returns becomes trivial.

这篇关于在CakePHP中的单元测试期间使用不同的电子邮件配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆