根据构造函数参数编写行为不同的类的规范

时间:2013-04-24 13:26:46

标签: php bdd phpspec

如果你有一个类根据构造函数的参数做出不同的响应,你如何编写该类的规范?

class Route
{
  function __construct($url, array $methods = array())
  {
    // stores methods and url in private member variables
    // creates a regex to match $url against incoming request URLs
  }

  public function isMatch($url)
  {
    // checks if the incoming request url matches against this url
  }
}

使用示例:

$a = new Route('/users/:id');
$a->isMatch('/users/1') // returns true;
$b = new Route('/users');
$b->isMatch('/users') // returns true

如果我使用phpspec中的let函数设置此类的规范:

class Route extends ObjectBehaviour
{
  function let() 
  {
    $this->beConstructedWith('/users/:id')
  }
}

我的规范只能检查此类的行为是否适用于其中一种情况。

我已经考虑过添加setter方法以允许我对此进行测试,但似乎我要打破封装以进行测试。

我正在努力寻找任何触及这一点的东西,所以我开始认为这可能是代码异味的情况。

2 个答案:

答案 0 :(得分:3)

beConstructedWith()并不总是需要从let()方法调用。您也可以从规格中调用它。

在我看来,以多种方式设置对象没有任何问题。但是,您应该避免使用doing too much work in the constructor

答案 1 :(得分:1)

  1. 构造函数应仅用于获取将在此处设置为成员属性的变量。这里不应该做进一步的逻辑......
  2. 按照第1点的想法,应该有另一个逻辑来确定接下来会发生什么(例如if Object->hasProperty(X) then do x()等)。
  3. 然后评论会很简单直截了当。
  4. 示例:

    class Route
    {
        private $url;
        private $methods = array();
    
        /**
         * Constructor method, sets the attributes to private member variables
         * @param string $url URL pattern
         * @param array $methods Methods that should be used with given URL
         */
        function __construct($url, $methods = array())
        {
            $this->url      = $url;
            $this->methods  = $methods;
        }
    
        // ...
    
    }