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