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!
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 🙂