2017-09-23 177 views
0

作爲一個練習,我試圖用PHPUnit達到100%的代碼覆蓋率,這幾乎就在那裏,但這是我發現很難的錯誤位。使用PHPUnit和PDO測試覆蓋率

我有一個例子類,我有一個類似的問題,我的真實代碼,確切的代碼不是問題,但行爲是相同的。

class DBAccess { 
    private $db; 

    public function __construct(\PDO $db) { 
     $this->db = $db; 
    } 

    public function select() { 
     $data = false; 
     if ($stmt = $this->db->prepare("select * from user")){ 
      if ($stmt->execute()){ 
       $data = $stmt->fetchAll(); 
      } 
      else { 
       echo "Something went wrong"; // How to get here! 
      } 
     } 
     return $data; 
    } 
} 

這是停止100%覆蓋的一條線。困難是我需要準備通過,但執行失敗。我已經通過傳遞無效的外鍵或字段到大表來處理更新,但是對於select,我不確定會出現什麼問題。

我的測試是...

class DBAccessTest extends TestCase { 
    private $pdo; 

    public function setUp() { 
     $this->pdo = new PDO("mysql:host=172.18.0.2;dbname=test", 
       "test", "RkqwD1gjOdjkrwTt"); 
     $this->pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 
    } 

    public function testSelect() { 
     $test = new DBAccess($this->pdo); 
     $this->assertTrue($test->select() != false); 
    } 
} 

有兩種可能性,我能想到的

  1. 假設,如果準備工作過,該執行的意志爲好,但也不是特別快樂接着就,隨即。
  2. 以某種方式覆蓋連接,使其以受控方式失敗。
+0

這是確切的功能?它沒有采取任何參數? – ishegg

+1

這是嘲笑的。 '\ PDO'應該用它的模擬來代替。 http://erichogue.ca/2013/02/best-practices/mocking-pdo-in-phpunit/ – Axalix

+0

@ishegg這不是確切的功能,因爲我提到它是一個簡單的例子。關鍵部分是,我無法想到一旦準備工作,如何做出選擇失敗。 –

回答

0

這正是PHPUnit's test doubles的用途。並且以面向對象的方式設計你的類,所以很容易向它們注入mock。

<?php 

use PHPUnit\Framework\TestCase; 

class DBAccessTest extends TestCase 
{ 
    public function test_something_goes_wrong() 
    { 
     // Create test doubles. 
     $stmtMock = $this->createMock(\PDOStatement::class); 
     $pdoMock = $this->createMock(\PDO::class); 

     // Configure the stubs. 
     $stmtMock->method('execute') 
       ->willReturn(false); 
     $pdoMock->method('prepare') 
       ->willReturn($stmtMock); 

     // Inject the mock. 
     $test = new DBAccess($pdoMock); 

     // Assert. 
     $this->assertFalse($test->select()); 
    } 
} 
+0

你真的在這裏測試正確的行爲嗎?這似乎只是因爲你特意告訴它而失敗。所以你真的在測試實現細節。如果只是爲了代碼覆蓋而進行測試,爲什麼不使用@codeCoverageIgnore?我正當地問道,我總是有這種測試的概念問題 – ishegg

+1

這是我之後的事情,我也會在其他幾個地方玩這個遊戲。至於測試正確的行爲,當然應用程序對失敗的反應與正常運行同樣重要。如果一個系統不能有條不紊地對問題做出反應,那麼重要的行動就會失去,裂縫和數字之間的差距就不再增加。爲了覆蓋目的,讓系統忽略代碼甚至更糟。 –