我正在尝试在个人PHP项目中进行单元测试,就像一个优秀的小程序员,我想要正确地完成它.从我听到你应该测试的是一个方法的公共接口,但我想知道这是否仍然适用于下面.
我有一个方法,在用户忘记密码的情况下生成密码重置令牌.该方法返回以下两种情况之一:如果一切正常,则为nothing(null),或者表示具有指定用户名的用户不存在的错误代码.
如果我只测试公共接口,如果用户名有效,如何确保密码重置令牌在数据库中,如果用户名无效,我怎么能不在数据库中?我应该在测试中进行查询以验证这一点吗?或者我应该假设我的逻辑是合理的?
现在这个方法非常简单,这不是什么大不了的事 - 问题在于同样的情况适用于许多其他方法.你在以数据库为中心的单元测试中做了什么?
代码,如有需要可供参考:
public function generatePasswordReset($username)
{
$this->sql='SELECT id
FROM users
WHERE username = :username';
$this->addParam(':username', $username);
$user=$this->query()->fetch();
if (!$user)
return self::$E_USER_DOESNT_EXIST;
else
{
$code=md5(uniqid());
$this->addParams(array(':uid' => $user['id'],
':code' => $code,
':duration' => 24 //in hours, how long reset is valid
));
//generate new code, delete old one if present
$this->sql ='DELETE FROM password_resets WHERE user_id=:uid;';
$this->sql.="INSERT INTO password_resets (user_id, code, expires)
VALUES (:uid, :code, now() + interval ':duration hours')";
$this->execute();
}
}
Run Code Online (Sandbox Code Playgroud)
至少对于我而言,单元测试的好处在于它向您展示了重构所需的位置.使用上面的示例代码,您基本上在一个方法中发生了四件事:
//1. get the user from the DB
//2. in a big else, check if user is null
//3. create a array containing the userID, a code, and expiry
//4. delete any existing password resets
//5. create a new password reset
Run Code Online (Sandbox Code Playgroud)
单元测试也很棒,因为它有助于突出依赖性.如上所示,此方法依赖于DB,而不是实现接口的对象.此方法与其范围之外的系统交互,实际上只能使用集成测试进行测试,而不是单元测试.单元测试用于确保工作单元的工作/正确性.
我建议你的generatePasswordReset方法应该重构为:
SELECT,DELETE和INSERT.OverwriteExistingPwdChangeRequests()来处理DELETE + INSERT.| 归档时间: |
|
| 查看次数: |
376 次 |
| 最近记录: |