Wie würden Sie mit PHPUnit eine WordPress-Funktion testen, die check_admin_referer() enthält?

Lesezeit: 4 Minuten

Ich habe gerade angefangen, PHPUnit mit WordPress zu lernen. Ich habe ein Plugin, das Petitionsdaten von change.org erhält. Eine der Funktionen der Admin-Klasse validiert Einstellungen aus einem WordPress-Adminbereich und ruft als Teil dieser Validierung auch `check_admin_referer() auf.

  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;

  }

Dieser PHPUnit-Test wird bestanden, wenn ich ihn auskommentiere check_admin_referer() aber ich kann es nicht durchbringen, wenn nicht.

  public function testValidateSettings() {    

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

  }  

Ich habe versucht, eine Nonce, Aktion und _wp_http_referer manuell und über festzulegen wp_nonce_field() über $_POST in tests/bootstrap.php und in der Testklasse selbst. Und ich habe ein bisschen über Scheinobjekte/Methoden gelesen, sehe aber nicht ganz, wie sie in diesem Fall verwendet werden könnten.

Ich bin wahrscheinlich völlig missverstanden, wie das alles funktioniert, aber jede Hilfe wäre sehr dankbar!

Benutzer-Avatar
Andrej Zerkus

Das Problem ist, dass Tests im Befehlszeilenmodus ausgeführt werden und der aktuelle Benutzer dort natürlich nicht authentifiziert wird.

Es gibt ein paar Alternativen, wie es funktioniert. Eine Möglichkeit besteht darin, entweder die Auth-Check-Funktion zu stubn check_admin_referer() oder dessen Basiswert wp_verify_nonce(). Aber es ist nicht der beste Ansatz, da die Tests dort Integrationscharakter haben, während Stubbing eher ein Ansatz für Unit-Tests ist.

Eine gute Lösung besteht darin, den Benutzer zu authentifizieren, damit die Tests bestehen. Du kannst es relativ einfach so machen:

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

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

Davon bin ich nicht überzeugt $this->plugin_admin->plugin_name wird funktionieren, da es sich um ein Privateigentum handeln könnte. Sie können es also einfach als fest codierten String übergeben:

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

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

Es wäre auch großartig, nach Ihrem Test aufzuräumen, also sollten Sie dies auf jeden Fall in Ihrem Testfall haben:

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

Ich glaube nicht, dass Sie die neu erstellte Nonce nach den Tests bereinigen müssen, da die WP-Originaltests das auch nicht bereinigen.

Das ist hübsch.


Verbesserung

Wenn alle Ihre Tests im Testfall eine Authentifizierung erfordern, möchten Sie möglicherweise die Nonce-Erstellung in setUp() – Dadurch wird der Testfall schöner, da der Teardown-Code mit dem Setup-Code übereinstimmt:

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());
}

Anregung

Installieren Sie Xdebug und stellen Sie über Ihre IDE eine Verbindung damit her – dies hilft Ihnen, den Code Schritt für Schritt durchzugehen und zu sehen, was nicht wie erwartet funktioniert. Das ist besser, als blind mit all diesen Nonces, HTTP-Referrern usw. zu kämpfen.


Notiz

Der WP-Code ist ziemlich traurig. Riesige Liste von Funktionen im globalen Namensraum, kein OOP, kein vollständiger Zyklus für die Anfrageverarbeitung (z. B. unerwartete die()) – ist wirklich frustrierend, weil es die Erweiterung der Codebasis und das Testen wirklich schwierig macht.

Seien Sie also auf weitere Kämpfe mit dem Code gefasst 🙂

  • Hallo @andrey-tserkus, danke, dass du dir die Zeit genommen hast, eine ausführliche Antwort und einen Kontext zu geben. Es funktionierte! Ich musste den Plugin-Namen wie von Ihnen vorgeschlagen als fest codierte Zeichenfolge übergeben. Guter Tipp, um es auch in setUp() zu integrieren, um es schöner zu machen! Nochmals vielen Dank – ich werde mich mit dem WP-Code auf zukünftige Kämpfe vorbereiten!

    – grüne Ziegel

    15. August 2016 um 8:55 Uhr

  • Danke, @AndreyTserkus. Diese Antwort hat mir auch am meisten geholfen. Ich konnte den $_REQUEST-Aspekt nicht zum Laufen bringen, entdeckte aber, wenn ich den aktuellen Benutzer festlegte, wp_verify_nonce würde funktionieren. Hat einen kurzen Beitrag geschrieben, der anderen beim Testen von WordPress helfen könnte. wp_verify_nonce und PHPUnit

    – jerdh

    17. Februar 2017 um 22:21 Uhr

1371530cookie-checkWie würden Sie mit PHPUnit eine WordPress-Funktion testen, die check_admin_referer() enthält?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy