模拟PHPUnit Test Suite的LDAP连接

Kla*_* S. 3 php phpunit ldap

我一直在使用PHPUnit一段时间,但突然碰上了一堵墙:嘲笑LDAP.我有一个小的抽象层,用于使用默认的LDAP PHP扩展与LDAP服务器通信.现在,我不知道如何模拟扩展的连接和功能,以便正确测试我的类.

文件系统和数据库模拟非常常见且易于设置,但目录服务器呢?:(

Mik*_*e B 5

您应该模拟LDAP适配器,而不是PHP扩展.文件系统和数据库模拟以相同的方式工作......它们实际上并不创建文件系统或数据库,它们只代表通常与这些数据源交互并模仿某些行为的类,就好像它确实存在一样.

例如:

// Load user 12345
$user = UserModel::find(12345); 
Run Code Online (Sandbox Code Playgroud)

通常,此调用将发送到数据库并查询用户12345.但是,我们已经模拟了PDO适配器并告诉它在使用预期参数调用其query()或execute()方法时响应数据.因此,虽然看起来我们已经模拟了整个数据库,但我们所做的一切都是模拟最接近数据库但离您自己的代码最远的类.

希望您使用的是具有LDAP适配器的身份验证系统,您可以使用模拟替换它.或者是PHP的ldap函数的包装类.

更新

最大的问题是你几乎在所有方法中都使用了基本的ldap函数.代码确实没问题..但单元测试很难.我通过创建一个处理所有通信的方法来解决这个问题,并对此做出了断言:

(免责声明:此代码没有逻辑意义,根本不起作用..仅用于示例目的)

class LDAP_Auth {

  public function authenticate($username, $password) {
    // Extra business logic or other things that need to be tested
    return $this->_callLdap('ldap_bind', $username, $password);
  }

  protected function _callLdap() {
    $args = func_get_args();
    $functionName = array_shift($args); // First argument should be the function name

    return call_user_func_array($functionName, $args);
  }
}
Run Code Online (Sandbox Code Playgroud)

所以每个ldap_*函数都是从同一个_callLdap()方法调用的.如果你想测试authenticate()方法,你所要做的就是:

  • 创建类本身的模拟对象
  • 模拟_callLdap方法并断言用正确的参数调用它一次
  • 然后authenticate()像平时那样调用

像这样的东西:

$ldapMock = $this->getMock('LDAP_Auth', array('_callLdap');
$ldapMock->expects($this->once())
  ->method('_callLdap')
  ->with(array('ldap_bind', 'mike', 'password'))
  ->will($this->returnValue(true));

$ldapMock->authenticate('mike', 'password');
Run Code Online (Sandbox Code Playgroud)

该测试断言该_callLdap方法使用params调用一次,array('ldap_bind', 'mike', 'password')确保其authenticate()正常运行