1

我正在尝试找出编写代码以进行更好的单元测试等的最佳方法。目前我有两个主要问题:

  1. 我使用服务容器在类方法中获取我需要的服务,我担心这可能不是最好的方法,因为我依赖这些服务首先准备好
  2. 我还使用一个主要的“设置”类,我可以跨模块/插件访问许多设置。我还担心这会对此设置产生不必要的依赖

一些示例代码来澄清我的问题:

class ABC
{
    function someFunction(){
        if(Container::get('settings')->get('status'))
        {
            Container::get('mailer')->send();
        }
    }
}

也许我应该做的就是首先通过构造方法注入这些?

4

2 回答 2

0

您可以进行以下操作:

class ABC
{
    private $_setting = null;
    private $_mailer = null;

    public function setSetting($setting)
    {
        $this->_setting = $setting;
    }

    public function getSetting()
    {
        return $this->_setting;
    }

    public function setMailer($mailer)
    {
        $this->_mailer = $mailer;
    }

    public function getMailer()
    {
        return $this->_mailer;
    }

    function someFunction(){
       if($this->_setting->get('status'))
       {
           $this->_mailer->send();
       }
   }
}

class SettingMock
{
     private $_attributes = array();

     public function setMock($attribute, $value)
     {
         $this->_attributes[$attribute] = $value; 
     }
     public function get($attribute)
     {
         return $this->_attributes[$attribute];
     }

}

class MailerMock
{
    private $_values = array();

    public function setValue($value)
    {
        $this->_values['return'] = $value;
    }

    public function send()
    {
        return $this->_values['return'];
    }
}

测试类:

class FooTest extends PHPUnit_Framework_TestCase
{
    public function testSendMail()
    {
         $settingMock = new SettingMock();
         $settingMock->setMock('status', true);

         $mailerMock = new MailerMock();
         $mailerMock->setValue(true);

         $testObject = new ABC();
         $testObject->setSetting($settingMock);
         $testObject->setMailer($mailerMock);

         $return = $testObject->someFunction();
         $this->assertTrue($return);
    }
}
于 2012-10-16T03:49:04.863 回答
0

您的服务容器看起来就像是服务定位器反模式。虽然服务定位器本身在极少数情况下可能很有用,但它始终是编写可测试(和可维护)代码时的主要障碍:

  • 由于它的全局/静态性质,很难(如果不是不可能的话)模拟它
  • 它隐藏了组件的依赖关系,从而影响了代码的可读性
  • 它在消费者代码和自身之间引入了紧密耦合

虽然其中一些问题可以解决,但不值得这样做。您的直觉是正确的,通常处理它的方法是将其重构为适当的 DI 模式,例如构造函数注入。

于 2012-10-16T10:40:55.270 回答