2012-04-12 20 views
3

Ich muss Tests für eine PHP-Klasse schreiben, die einen Ressourcentyp verwendet, der von einer von uns verwendeten Apache-Erweiterung erstellt wurde, aber sagen wir, es ist eine Datenbankklasse mit dem Ressourcentyp mysql.mock php's Ressourcentyp für Unittests

offensichtlich möchte ich diese globalen Funktionen spotten, aber wie man den Rückgabetyp fälscht, wenn die Klasse überprüft, ob die Ressource gut erstellt wurde?

die Resource-Seite in php doc sogar einen Kommentar über die Unfähigkeit von Mocks zum Testen. Ist das die endgültige Antwort?

lassen Sie uns sagen, dass ich die (lame Beispiel) Code haben:

class DB { 
    function init(){ 
    $this->handle = mysql_connect('myserver'); 
    if(get_resource_type($this->handle) != 'mysql') return false; 
     return true; 
    } 
} 

und dann die Tests, die für einen Erfolg und einen Fehler zu testen, von mysql_connect spöttisch.

Antwort

4

Vielleicht bist du ein bisschen weit weg. Wirklich, Ressourcen sind völlig in Ordnung, um mit PHP zu testen, können Sie ihren Typ usw. pp ..

Was ist nicht einfach zu testen sind die Abhängigkeiten, die sie darstellen. Normalerweise injizieren Sie diese nicht, aber Sie codieren diese Ressourcen. Nennen wir es objektorientiert.

Zentrale ist das Objekt (Ressource) und der Code im prozeduralen Stil hat immer die Abhängigkeit dieser Ressource. Lassen Sie sich als Beispiel curl nehmen:

$url = 'http://example.com/'; 
$handle = curl_init($url); 
curl_exec($handle); 

Da dieses Verfahren Stil um das $handle Objekt es nicht mockable im Sinne ist die Funktionalität mit einem Mock zu ersetzen, wenn curl eine Abhängigkeit von einem anderen Code. So müssen Sie es wickeln zuerst machen es injizierbare:

$url = 'http://example.com/'; 
$curl = new Curl($url); 
$curl->exec(); 

Dieses kommt mit dem Preis, den Sie benötigen die Ressource zentrierte Objektorientierung in einem einfachen alten PHP-Objekt zu konvertieren:

class Curl 
{ 
    private $handle; 
    public function __construct($url) { 
     $this->handle = curl_init($url); 
    } 
    public function exec() { 
     return curl_exec($this->handle); 
    } 
} 

Es ist einfach, jetzt, um es zu verspotten. Das Gute daran ist, dass dies oft möglich ist. Normalerweise sollten die Ressourcen selbst keine Einschränkungen für Tests vorsehen, es ist nur eine Kapselung, die fehlt, daher müssen Sie sie zuerst hinzufügen.

Einige APIs, wie die IMAP-Erweiterung, erlauben aufgrund des globalen statischen Status keine Erstellung einer sauberen Objektschnittstelle, im Falle der IMAP-Erweiterung ist es die Fehlerbehandlung. Aber es kommt immer näher und wenn die Mängel dokumentiert sind, hilft das auch.

+0

Ich sehe Sie nicht Punkt ... Was wäre, wenn ich diese Klasse testen sollte, und direkt vor curl_exec überprüfte es die Art der Ressource war die ursprüngliche Curl-Typ? und ich wollte es nicht mit echten Curl-Funktionen? – gcb

+1

@gcb: Entweder möchten Sie die Curl-Klasse in einem Unit-Test testen (wenn Sie dies tun, ist das Handle ein internes und muss nicht getestet werden) oder Sie möchten eine andere Komponente testen, die das Curl verwendet 'Klasse, dann kannst du es der Klasse' Curl' nachspielen. – hakre

+0

Wenn ich die 'Curl'-Klasse teste, wie vermeide ich es dann, Webserver zu treffen und inkonsistent zu sein? – gcb

0

Dies kann den Menschen helfen, die versuchen, PHP-Funktionen wie Locken zu verspotten: https://github.com/IcecaveStudios/isolator

Es Sie sie von Ihrem Code zu isolieren, ermöglicht, so dass Sie normale spöttischen Techniken verwenden.

Verwandte Themen