2016-05-20 18 views
1

Können Sie mir sagen, wo das Problem ist? Ich habe eine Datei GeneratorTest.ph p mit den folgenden Tests:Mothery & PHPUnit: Methode existiert nicht für dieses Mock-Objekt

<?php 

namespace stats\Test; 

use stats\jway\File; 
use stats\jway\Generator; 

class GeneratorTest extends \PHPUnit_Framework_TestCase 
{ 

    public function tearDown() { 
     \Mockery::close(); 
    } 

    public function testGeneratorFire() 
    { 
     $fileMock = \Mockery::mock('\stats\jway\File'); 
     $fileMock->shouldReceive('put')->with('foo.txt', 'foo bar')->once(); 
     $generator = new Generator($fileMock); 
     $generator->fire(); 
    } 

    public function testGeneratorDoesNotOverwriteFile() 
    { 
     $fileMock = \Mockery::mock('\stats\jway\File'); 
     $fileMock->shouldReceive('exists') 
      ->once() 
      ->andReturn(true); 

     $fileMock->shouldReceive('put')->never(); 

     $generator = new Generator($fileMock); 
     $generator->fire(); 
    } 
} 

und hier sind Datei und Generator Klassen:

file.php:

class File 
{ 
    public function put($path, $content) 
    { 
     return file_put_contents($path, $content); 
    } 

    public function exists($file_path) 
    { 
     if (file_exists($file_path)) { 
      return true; 
     } 
     return false; 
    } 
} 

Generator.php:

class Generator 
{ 
    protected $file; 

    public function __construct(File $file) 
    { 
     $this->file = $file; 
    } 

    protected function getContent() 
    { 
     // simplified for demo 
     return 'foo bar'; 
    } 

    public function fire() 
    { 
     $content = $this->getContent(); 
     $file_path = 'foo.txt'; 

     if (! $this->file->exists($file_path)) { 
      $this->file->put($file_path, $content); 
     } 
    } 

} 

Also, wenn ich diese Tests laufen lasse, erhalte ich folgende Meldung: BadMethodCallException: Methode ... :: exists() existiert nicht auf dieser Mock-Objekt.

enter image description here

+0

Versuchen Sie, 'withAnyArgs()' auf die Verspottung der Datei als Beispiel: '$ fileMock-> shouldReceive ('existiert') -> einmal() -> withAnyArgs() -> andReturn (true); ' – Matteo

+0

Ich habe versucht, das gleiche Problem existiert noch. – PeraMika

Antwort

4

Die Fehlermeldung erscheint mir klar. Sie haben nur eine Erwartung für die put-Methode festgelegt, aber nicht exists. Die exists Methode wird von der Klasse in Test in allen Codepfaden aufgerufen.

public function testGeneratorFire() 
{ 
    $fileMock = \Mockery::mock('\stats\jway\File'); 
    $fileMock->shouldReceive('put')->with('foo.txt', 'foo bar')->once(); 

    //Add the line below 
    $fileMock->shouldReceive('exists')->once()->andReturn(false); 

    $generator = new Generator($fileMock); 
    $generator->fire(); 
} 
+0

Eine Frage: Wenn wir ein Mock-Objekt wie dieses erzeugen: '$ fileMock = \ Mothery :: mock ('\ stats \ jway \ File');' dann geben alle Methoden in diesem Mock-Objekt standardmäßig 'NULL' zurück, richtig ?. Wenn ja, warum müssen wir die 'exists'-Methode so einrichten, wie Sie es getan haben, wird NULL zurückgegeben und die 'put'-Methode wird trotzdem ausgeführt? – PeraMika

+1

Sie müssen 'shouldIgnoreMissing()' hinzufügen, damit das Mock-Objekt null zurückgibt, wenn Sie keine Erwartung festgelegt haben. In diesem Fall wäre es besser, streng zu sein und false zurückzugeben, weil ein boolescher Wert das ist, was die Schnittstelle von exists definiert. Wenn Sie 'if (! $ This-> file-> exists ($ file_path))' in 'if ($ this-> file-> exists ($ file_path) === false)) schreiben, wird Ihr Komponententest abgebrochen. –

+0

"Sie haben nur eine Erwartung für die put-Methode festgelegt, aber nicht existiert. Die exists-Methode wird von der getesteten Klasse in allen Codepfaden aufgerufen." Kannst du das mehr erklären? Warum müssen wir Testerwartungen für Methoden erstellen, die zufällig aufgerufen werden? – alexw

Verwandte Themen