2017-09-23 137 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

这是我之后的事情,我也会在其他几个地方玩这个游戏。至于测试正确的行为,当然应用程序对失败的反应与正常运行同样重要。如果一个系统不能有条不紊地对问题做出反应,那么重要的行动就会失去,裂缝和数字之间的差距就不再增加。为了覆盖目的,让系统忽略代码甚至更糟。 –