2016-08-28 42 views
0

私はしばらくこの問題に巻き込まれています。なぜPHPunitが関数が呼び出されているのかわかりません。PHPunitメソッドが1回呼び出されると予想され、実際に0回呼び出されます

これは私がテストしようとしているコードです:

public function handle() 
{ 
    $path = $this->request->getPath(); 
    $requestMethod = $this->request->getMethod(); 


    if (!$path) { 
     $this->redirect('home'); 
    } else if (!$this->isMethodPathFound($path, $requestMethod)) { 
     $this->redirect('404'); 
    } else { 
     $handler = $this->getControllerFullName($this->routes[$path]['handler']); 
     if (is_callable($handler)) { 
      call_user_func($handler); 
     } else { 
      $this->redirect('404'); 
     } 
    } 
} 

/** 
* @param string $path 
* @param int $statusCode 
*/ 
public function redirect($path, $statusCode = 303) 
{ 
    if (defined('TESTING_ENVIRONMENT') && TESTING_ENVIRONMENT) { 
     return; 
    } 
    header(
     'Location: ' . $this->request->getProtocol() . 
     $this->request->getHost() . '/' . $path, 
     true, 
     $statusCode 
    ); 
    die(); 
} 

それはPHPUnitの実行にトリガしないようにTESTING_ENVIRONMENT変数はヘッダー機能用に設定されている(私は別のクラスを作成する必要はありませんただ一つのテストのためにそれを模擬できるようにすることリダイレクト機能を持っている)、これはテストコードです:

public function testHandlePathIsEmpty() 
{ 
    $requestMock = $this->getMockBuilder('\services\Request')->getMock(); 
    $requestMock->expects($this->once())->method('getPath')->willReturn(''); 
    $requestMock->expects($this->once())->method('getMethod')->willReturn('GET'); 
    $routerMock = $this->getMockBuilder('\services\Router') 
     ->setConstructorArgs([$this->routes, $requestMock]) 
     ->enableProxyingToOriginalMethods() 
     ->getMock(); 
    $routerMock->expects($this->once())->method('redirect') 
     ->with('asdasd')->willReturn(true); 
    $routerMock->handle(); 
} 

$ routerMockオブジェクトは間違いなく「リダイレクト」機能を呼び出す必要があり、それはそれは取得しないことを言います私がvar_dump /関数内で死ぬときにも、それが呼び出されます。それの中に入る。

ありがとうございました!

答えて

1

phpunitのエラーが完全に出力されていることを躊躇していましたが、あなたのメソッドは呼び出されていない可能性が非常に高いですが、定義したすべての期待通りには呼び出されません。

あなたのコード

$routerMock->expects($this->once())->method('redirect') 
     ->with('asdasd')->willReturn(true); 

は、以下の期待に変換します。方法redirectは、引数'asdasd'に1回だけ呼び出されなければならないとtrueを返します。

メソッドにはasdasdが渡されていません。あなたのテストは、withの期待を取り除くと成功する可能性が高いです。

0

これを明確にするだけです。あなたがテストしたいクラスを模擬しなければならない場合、あなたのコードは複雑になり、別の方法でロジックを実装することを考えるべきです。

RequestRouterモック(ルータモックはあなたがそれを使用しないのでロジックがないかもしれません)を渡して新しいインスタンスを作成し、次にあなたのコード:あなたのユニットテストで

public function handle() 
{ 
    $request = $this->request; 
    $path = $request->getPath(); 
    if (!$path) { 
     $this->redirect('home'); 
    } else if (!$this->isMethodPathFound($path, $request->getMethod())) { 
     $this->redirect('404'); 
    } else { 
     $handler = $this->getControllerFullName($this->routes[$path]['handler']); 
     if (is_callable($handler)) { 
      call_user_func($handler); 
     } else { 
      $this->redirect('404'); 
     } 
    } 
} 

、あなたが今だけ

$requestMock 
    ->expects($this->never()) 
    ->method('getMethod'); 

のためにテストすることができ、私はこれが唯一の実行されていないために、第2ケースをカバーするだろうが、三番目はaswell起こりうることがわかり。それは常にあなたのコードが十分にクリーンでない理由です。 KISSとSOLIDについて、コードをよりテスト可能にするために何かを読んでください。このメソッドは、正しくテストできるほど複雑すぎます。

+0

私がルータクラスを嘲笑している理由は、リダイレクト機能を無効にし、その機能をテストしないことです。なぜなら、それはすべてPHPのグローバル関数なので、正しい場所で呼び出されるようにしたいだけです。そしてSOLIDについては、このクラスは単一の責任であり、その依存関係はそれに注入され、拡張可能であり、Liskovの置換にはかなり容易に従います。 PHPUnitでは、関数が実行されて例外がスローされることがわかりませんでした。 – Bola

関連する問題