PHPUnit如何测试包含check_admin_referer()的Wordpress函数?

时间:2016-08-12 16:06:01

标签: php wordpress phpunit

我刚开始用Wordpress学习PHPUnit。我有一个插件可以从change.org获取请愿数据。其中一个管理类函数验证来自Wordpress管理区域的设置,并在此验证过程中调用`check_admin_referer()。

  public function sc_validate_settings() {
    //check nonce field is valid
    check_admin_referer($this->plugin_name, 'security');    

    //get new settings 
    $settings = $this->sc_clean_new_settings();

    //validate url
    $valid_url = $this->sc_validate_url($settings['petition_url']);

    //validate api_key
    $valid_api_key = $this->sc_validate_api_key($settings['petition_api_key']);

    if ($valid_url && $valid_api_key) {

      $this->clean_settings = $settings;
      return true;

    }

    return false;

  }

如果我注释掉check_admin_referer(),那么这个PHPUnit测试会通过,但如果没有,我就无法通过。

  public function testValidateSettings() {    

    $this->assertTrue($this->plugin_admin->sc_validate_settings());

  }  

我尝试在tests / bootstrap.php和测试类本身中通过wp_nonce_field()手动设置nonce,action和_wp_http_referer并通过$_POST设置。我已经阅读了一些关于模拟对象/方法的内容,但是在这个实例中并没有看到它们如何被使用。

我可能完全误解了这一切是如何运作的,但是我们将非常感谢任何帮助!

1 个答案:

答案 0 :(得分:6)

问题是测试在命令行模式下运行,当然,当前用户未在那里进行身份验证。

如何使其发挥作用还有几种选择。一种选择是存根auth-check函数check_admin_referer()或其基础wp_verify_nonce()。但这不是最好的方法,因为测试有集成的味道,而存根更像是单元测试的方法。

一个好的解决方案是验证用户以使测试通过。你可以这样做比较容易:

public function testValidateSettings() {
    $_REQUEST['security'] = wp_create_nonce($this->plugin_admin->plugin_name);

    $this->assertTrue($this->plugin_admin->sc_validate_settings());
}

我不相信$this->plugin_admin->plugin_name会起作用,因为它可能是私人财产。所以你可以把它作为硬编码字符串传递:

public function testValidateSettings() {
    $_REQUEST['security'] = wp_create_nonce('whatever your plugin name is');

    $this->assertTrue($this->plugin_admin->sc_validate_settings());
}

在测试之后进行清理也很棒,所以在测试用例中一定要有这个:

public function tearDown() {
    unset($_REQUEST['security']);
}

我不认为你需要在测试后清理新创建的nonce,因为WP原始测试也不会清除它。

这很漂亮。

<强>改进

如果测试用例中的所有测试都需要身份验证,您可能希望将nonce-creation设置为setUp() - 这将使测试用例更漂亮,因为拆卸代码将与设置一致:

public function setUp() {
    $_REQUEST['security'] = wp_create_nonce('whatever your plugin name is');
}

public function tearDown() {
    unset($_REQUEST['security']);
}

public function testValidateSettings() {
    $this->assertTrue($this->plugin_admin->sc_validate_settings());
}

<强>建议

安装Xdebug并通过IDE连接到它 - 这将帮助您逐步完成代码,看看哪些内容无法正常工作。这比盲目地与所有这些nonce,http引用等等进行斗争更好。

注意

WP代码非常难过。全局命名空间中的大量函数列表,缺少OOP,没有完整的请求处理周期(例如,意外的die()) - 实在令人沮丧,因为它使得代码库的扩展和测试非常困难。

所以准备好与代码进行更多的战斗:)