gpt4 book ai didi

php - 模拟 Symfony Ldap::create 用于单元测试

转载 作者:可可西里 更新时间:2023-11-01 13:29:11 25 4
gpt4 key购买 nike

最近我一直在研究 LDAP authentication provider对于 MediaWiki。在我看来,我已经尝试解决这个问题好几天了,但无法提出解决方案。

上下文

我开发这个插件的方式是允许配置我们将连接到的多个服务器。如果我们无法连接到一个服务器,我们将尝试下一个……以此类推,直到所有连接都用完。

为了促进这一点,我在我的类中有一个函数,它循环遍历尝试连接的服务器,直到一个成功:

private function connect( LdapAuthenticationRequest $req ) {
$dn = $this->config->get( 'BindDN' )[$req->domain];
$pass = $this->config->get( 'BindPass' )[$req->domain];
$servers = $this->config->get( 'Servers' )[$req->domain];
$encryption = $this->config->get( 'EncryptionType' )[$req->domain];
if ( false === $dn ) {
$msgkey = 'ldapauth-attempt-bind-search';
$bind_with = [ null, null ];
} else {
$msgkey = 'ldapauth-attempt-bind-dn-search';
$bind_with = [ $dn, $pass ];
}
$message = new Message( $msgkey, [
'dn' => "{$dn}@{$req->domain}",
] );
$this->logger->info( $message->text() );
foreach ( $servers as $server ) {
if ( false === $server ) {
continue;
}
$ldap = Ldap::create( 'ext_ldap', [
'host' => $server,
'encryption' => $encryption
] );
// Attempt bind - on failure, throw an exception
try {
call_user_func_array( [ $ldap, 'bind' ], $bind_with );
$this->server = $server;
$this->encryption = $encryption;
// log successful bind
$msgkey = 'ldapauth-bind-success';
$message = wfMessage( $msgkey )->text();
$this->logger->info( $message );
return $ldap;
} catch ( SymException $e ) {
if ( false === $dn ) {
$msgkey = 'ldapauth-no-bind-search';
} else {
$msgkey = 'ldapauth-no-bind-dn-search';
}
$message = new Message( $msgkey, [
'dn' => "{$dn}@{$req->domain}",
] );
$message = $message->text();
$this->logger->info( $message );
$this->logger->debug( $e->getMessage() );
}
}

我一直在努力想出一个更好的方法来做到这一点,一个可以让我更好地对这个类进行单元测试的方法,但到目前为止我还是一片空白。

我陷入这个问题的很大一部分原因是 Symfony 的 LDAP 适配器本质上是硬耦合到我的代码中的,因为对连接的调用是对 Symfony 代码库的静态调用。即我无法传入某个描述的 connector 实例,然后尝试连接。也许我只是用我自己的连接包装器包装 Ldap::create 吗?

最佳答案

由于您使用的是 Symfony,我想您最好的选择是使用框架的依赖注入(inject)来注入(inject) LDap 对象。但是我不是 Symfony 的专家。所以作为一个简单的 hack,我会这样做:

  private function connect($req)
{
$dn = $this->config->get('BindDN')[$req->domain];
$pass = $this->config->get('BindPass')[$req->domain];
$servers = $this->config->get('Servers')[$req->domain];
$encryption = $this->config->get('EncryptionType')[$req->domain];
if (false === $dn) {
$msgkey = 'ldapauth-attempt-bind-search';
$bind_with = [null, null];
} else {
$msgkey = 'ldapauth-attempt-bind-dn-search';
$bind_with = [$dn, $pass];
}
$message = new Message($msgkey, [
'dn' => "{$dn}@{$req->domain}",
]);
$this->logger->info($message->text());
foreach ($servers as $server) {
if (false === $server) {
continue;
}
$ldap = $this->createLDAPObject($server, $encryption);
// Attempt bind - on failure, throw an exception
try {
call_user_func_array([$ldap, 'bind'], $bind_with);
$this->server = $server;
$this->encryption = $encryption;
// log successful bind
$msgkey = 'ldapauth-bind-success';
$message = wfMessage($msgkey)->text();
$this->logger->info($message);
return $ldap;
} catch (SymException $e) {
if (false === $dn) {
$msgkey = 'ldapauth-no-bind-search';
} else {
$msgkey = 'ldapauth-no-bind-dn-search';
}
$message = new Message($msgkey, [
'dn' => "{$dn}@{$req->domain}",
]);
$message = $message->text();
$this->logger->info($message);
$this->logger->debug($e->getMessage());
}
}
}

/**
* @param $server
* @param $encryption
* @return mixed
*/
public function createLDAPObject($server, $encryption)
{
return Ldap::create('ext_ldap', [
'host' => $server,
'encryption' => $encryption
]);
}

然后,你可以mock成员方法createLDAPObject而不是mock静态方法Ldap::create,这样应该更简单。

但是,我建议您重构代码,使其更具可读性和可测试性。

1- 首先,call_user_func_array() 并不是真正的测试友好型,我认为您的要求不太动态,因此您可以用 $ldap-> 替换该行绑定(bind)($bind_with[0],$bind_with[1]);

2- 您的connect 方法太大,无法测试。请阅读 Code Smells - Long Methods

3- 该方法可以通过将表示与逻辑分离来重构为更小的版本。例如,您正在获取 Message 对象以从 $msgkey 获取文本,只是为了记录它,这无助于代码的可读性和测试能力。

这是我对这件事的最初想法:)

快乐的编码和测试:)

关于php - 模拟 Symfony Ldap::create 用于单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52771360/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com