1

我有一个巴黎模特,像这样:

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() 方法?我认为答案可能很简单,但我真的无法理解它......

4

2 回答 2

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 类中实现一些电子邮件和密码设置器。一般来说,这应该可以解决问题:)

于 2013-02-07T18:08:44.563 回答
1

对此有几点想法。

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

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

通过以这种方式重新构建您的架构UserModel,您将能够充分利用 PHPSpec 中的 Mocking(这里很棒)来专注于实现您的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;
    }
}
于 2013-04-09T00:21:56.213 回答