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

How would you PHPUnit test a Wordpress function containing check_admin_referer()?

我刚刚开始使用 Wordpress 学习 PHPUnit。我有一个从 change.org 获取请愿数据的插件。其中一个管理 class 函数验证来自 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;

  }

如果我注释掉这个 PHPUnit 测试通过 check_admin_referer() 但如果不注释我就无法通过。

  public function testValidateSettings() {    

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

  }  

我试过在 tests/bootstrap.php 中通过 wp_nonce_field() 通过 $_POST 手动设置随机数、动作和 _wp_http_referer 并在测试中class 本身。我读过一些关于 mock objects/methods 的内容,但不太明白在这种情况下如何使用它们。

我可能完全误解了这一切的工作原理,但我们将不胜感激任何帮助!

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

有几种方法可以让它发挥作用。一种选择是存根 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']);
}

我认为您不需要在测试后清除新创建的随机数,因为 WP 原始测试也不会清除它。

太好了。


改善

如果测试用例中的所有测试都需要身份验证,您可能希望将随机数创建放入 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 连接到它 - 这将帮助您逐步检查代码并查看有什么不符合您的预期。这比盲目地与所有那些 nonces、http referrers 等作斗争要好。


备注

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

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