2013-04-04 128 views
3

我按照本教程:http://jtreminio.com/2013/03/unit-testing-tutorial-part-5-mock-methods-and-overriding-constructors/。學習如何運作PHPUnit的好教程。軟斷言和模擬方法測試失敗

但我無法理解,因爲測試未通過。

失敗是:

Method was expected to be called 1 times, actually called 0 times. 

在這部分代碼:

 $badCode->expects($this->once()) 
      ->method('checkPassword') 
      ->with($password); 

但因爲下軟斷言checkPassword方法內運行,並通過測試,這是不可能的。

 $badCode->expects($this->once()) 
      ->method('callExit'); 

它失敗了,因爲是一個模擬方法,行爲是不同的?或者代碼錯了?

爲了便於理解,附上所有文件,這是一個小例子。

控制檯

PHPUnit 3.7.18 by Sebastian Bergmann. 

FYOU SHALL NOT PASS............ 

Time: 0 seconds, Memory: 6.00Mb 

There was 1 failure: 

1) phpUnitTutorial\Test\BadCodeTest::testAuthorizeExitsWhenPasswordNotSet 
Expectation failed for method name is equal to <string:checkPassword> when invoked 1 time(s). 
Method was expected to be called 1 times, actually called 0 times. 


FAILURES! 
Tests: 13, Assertions: 14, Failures: 1. 

BadCode.php

<?php 

namespace phpUnitTutorial; 

class BadCode 
{ 
    protected $user; 

    public function __construct(array $user) 
    { 
     $this->user = $user; 
    } 

    public function authorize($password) 
    { 
     if ($this->checkPassword($password)) { 
      return true; 
     } 

     return false; 
    } 

    protected function checkPassword($password) 
    { 
     if (empty($user['password']) || $user['password'] !== $password) { 
      echo 'YOU SHALL NOT PASS'; 
      $this->callExit(); 
     } 

     return true; 
    } 

    protected function callExit() 
    { 
     exit; 
    } 
} 

BadCodeTest.php

<?php 

namespace phpUnitTutorial\Test; 

class BadCodeTest extends \PHPUnit_Framework_TestCase 
{ 
    public function testAuthorizeExitsWhenPasswordNotSet() 
    { 
     $user = array('username' => 'jtreminio'); 
     $password = 'foo'; 

     $badCode = $this->getMockBuilder('phpUnitTutorial\BadCode') 
      ->setConstructorArgs(array($user)) 
      ->setMethods(array('callExit')) 
      ->getMock(); 

     $badCode->expects($this->once()) 
      ->method('checkPassword') 
      ->with($password); 

     $badCode->expects($this->once()) 
      ->method('callExit'); 

     $this->expectOutputString('YOU SHALL NOT PASS'); 

     $badCode->authorize($password); 
    } 
} 

有人能幫助我嗎?謝謝!

更新

的博客更新瞭解決方案本教程的作者。 不能對模擬方法做任何斷言,只有存根。

BadCode.php

<?php 

namespace phpUnitTutorial; 

class BadCode 
{ 
    protected $user; 

    public function __construct(array $user) 
    { 
     $this->user = $user; 
    } 

    public function authorize($password) 
    { 
     if ($this->checkPassword($password)) { 
      return true; 
     } 

     return false; 
    } 

    protected function checkPassword($password) 
    { 
     if (empty($this->user['password']) || $this->user['password'] !== $password) { 
      echo 'YOU SHALL NOT PASS'; 
      $this->callExit(); 
     } 

     return true; 
    } 

    protected function callExit() 
    { 
     exit; 
    } 
} 

BadCodeTest.php

<?php 

namespace phpUnitTutorial\Test; 

class BadCodeTest extends \PHPUnit_Framework_TestCase 
{ 
    public function testAuthorizeExitsWhenPasswordNotSet() 
    { 
     $user = array('username' => 'jtreminio'); 
     $password = 'foo'; 

     $badCode = $this->getMockBuilder('phpUnitTutorial\BadCode') 
      ->setConstructorArgs(array($user)) 
      ->setMethods(array('callExit')) 

     $badCode->expects($this->once()) 
      ->method('callExit'); 

     $this->expectOutputString('YOU SHALL NOT PASS'); 

     $badCode->authorize($password); 
    } 
} 

回答

0

作者在這裏 - 我欺騙了這部分,AppFog(我的主機)有免費帳戶(我的)的問題,所以我現在無法更新它。

而且,是的,它應該是在$this->usercheckPassword()

+0

好吧,我等待解決方案! Muchas Gracias! – Sangar82 2013-04-04 19:48:58

+1

嘿@ Sangar82代碼已經更新。抱歉的混亂! – 2013-04-04 19:57:27

+0

你已經刪除了$ badCode-> expect($ this-> once()) - >方法('checkPassword') - > with($ password);但爲什麼?這似乎應該工作,但我不明白,因爲在刪除這些行之前測試失敗 – Sangar82 2013-04-04 20:08:23

0

你缺少setMethods的方法:

->setMethods(array('callExit')) 

您需要添加checkPassword太多,如果你想檢查它是否被調用。

+0

我認爲這太(它可能是正確的),但例子仍然無法工作 – hek2mgl 2013-04-04 17:17:45

+1

這個例子是學習模擬和存根方法之間的差異。在這個例子中,checkPassword不是int setMethods,因爲它是一個模擬方法,並且callExit一個存根方法 – Sangar82 2013-04-04 17:26:11

+1

@ Sangar82是的,你是對的。我已經學會了......感謝教程。現在我理解你的代碼,它看起來沒問題。你需要'callExit()'作爲存根,否則會結束測試套件(使用exit)。將需要更深入的測試。你使用哪個PHPUnit版本?但是你應該做的一件事(儘管)它不直接屬於這個問題:在'checkPassword()' – hek2mgl 2013-04-04 18:08:00