使用PHPSpec2测试Paris模型

时间:2012-10-31 07:41:20

标签: php phpspec

我有一个Paris模型,有这样的东西:

class User extends Model
{
    public function authenticate($signature)
    {
        $hash = hash_hmac('sha256', $this->email, $this->password);

        if ($hash == $signature)
            $this->_authenticated = true;

        return $this->_authenticated;
    }
}

我想用PHPSpec2对此进行规范,但我遇到了一些问题。我想做点什么:

$this->authenticate('test')->shouldReturn(true);

但是如何在我的规范中访问authenticate()方法?我认为答案可能很简单,但我真的无法理解它......

2 个答案:

答案 0 :(得分:2)

<?php

namespace spec;

use PHPSpec2\ObjectBehavior;

class UserSpec extends ObjectBehavior
{
    function it_should_be_initializable()
    {
        $this->shouldHaveType('User');
    }

    function it_should_authenticate_if_proper_signature_given()
    {
        $signature = '...';
        $this->setEmail('...');
        $this->setPassword('...');

        $this->authenticate($signature)->shouldReturn(true);
    }
}

您需要先在规范中使用电子邮件和密码创建签名。在User类中也为电子邮件和密码实现一些setter。一般来说应该这样做:)

答案 1 :(得分:1)

对此有点想法。

您的用户模型正在与协作者合作以实现其自身行为 - 此协作者是hash_hmac函数。 PHPSpec的黄金法则是Subject Under Specification,一次只能处理一个类,稍后会考虑协作者的实现细节。我发现这有助于我设计关注分离原则的课程,我经常发现自己在问这个问题 - 这个课程究竟关心什么?

例如,您的UserModel不应该真正关心您的系统使用哪种哈希算法来保护密码。然而,它可以知道一个对象,称之为HashingProvider,它能够散列密码,甚至只接收一个或多个字符串并返回某种散列表示。

通过以这种方式重新构建UserModel,您将能够充分利用PHPSpec中的模拟(great talk here),专注于首先实施UserModel然后转到HashingProvider

您的规范可能如下所示:

<?php

namespace spec;
use PHPSpec2\ObjectBehavior;

class User extends ObjectBehavior
{
   function it_should_be_initializable()
   {
        $this->shouldHaveType('User');
   }

   /**
    * @param /Some/HashingProvider $hashProvider
    */
   function it_should_authenticate_if_proper_signature_given($hashProvider)
   {
      $this->setEmail('email');
      $this->setPassword('password');
      $hashProvider->hash('email', 'password')->willReturn('signature');

      $this->authenticate('signature', $hashProvider)->shouldReturn(true);
   }

   /**
    * @param /Some/HashingProvider $hashProvider
    */
   function it_should_not_authenticate_if_invalid_signature_given($hashProvider)
   {
      $this->setEmail('email');
      $this->setPassword('password');
      $hashProvider->hash('email', 'password')->willReturn('signature');

      $this->authenticate('bad_signature', $hashProvider)->shouldReturn(false);
   }
}

您的用户模型可以按照规范描述的方式使用该协作者:

<?php
class User extends Model
{
    public function authenticate($signature, $hashProvider)
    {
        $hash = $hashProvier->hash($this->email, $this->password);

        if ($hash == $signature)
            $this->_authenticated = true;

        return $this->_authenticated;
    }
}