2009-09-28 30 views
30

一個關鍵考慮下面的類:的PHPUnit:驗證陣列與給定值

<?php 
class Example { 
    private $Other; 

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

    public function query() 
    { 
     $params = array(
      'key1' => 'Value 1' 
      , 'key2' => 'Value 2' 
     ); 

     $this->Other->post($params); 
    } 
} 

這測試用例:

<?php 
require_once 'Example.php'; 
require_once 'PHPUnit/Framework.php'; 

class ExampleTest extends PHPUnit_Framework_TestCase { 

    public function test_query_key1_value() 
    { 
     $Mock = $this->getMock('Other', array('post')); 

     $Mock->expects($this->once()) 
       ->method('post') 
       ->with(YOUR_IDEA_HERE); 

     $Example = new Example($Mock); 
     $Example->query(); 
    } 

如何驗證$params(這是一個數組)和傳遞給$Other->post()包含名爲'key1'的鍵值爲'值1'?

我不想驗證所有的數組 - 這只是一個示例代碼,在實際代碼中,傳遞的數組有更多的值,我想驗證那裏只有一個鍵/值對。

$this->arrayHasKey('keyname'),我可以用它來驗證密鑰是否存在。

還有$this->contains('Value 1'),它可以用來驗證數組是否有這個值。

我甚至可以結合這兩個與$this->logicalAnd。但是這當然不能達到預期的效果。

到目前爲止,我一直在使用returnCallback,捕獲整個$ params,然後對此做出斷言,但是可能有另一種方法來做我想做的事情嗎?

+1

$ this-> attribute(Constraint,value)能夠完成我之後的工作,但它不適用於數組。 – 2009-09-28 14:21:35

回答

7

我最終創建了我自己的約束類,基於屬性

<?php 
class Test_Constraint_ArrayHas extends PHPUnit_Framework_Constraint 
{ 
    protected $arrayKey; 

    protected $constraint; 

    protected $value; 

    /** 
    * @param PHPUnit_Framework_Constraint $constraint 
    * @param string      $arrayKey 
    */ 
    public function __construct(PHPUnit_Framework_Constraint $constraint, $arrayKey) 
    { 
     $this->constraint = $constraint; 
     $this->arrayKey = $arrayKey; 
    } 


    /** 
    * Evaluates the constraint for parameter $other. Returns TRUE if the 
    * constraint is met, FALSE otherwise. 
    * 
    * @param mixed $other Value or object to evaluate. 
    * @return bool 
    */ 
    public function evaluate($other) 
    { 
     if (!array_key_exists($this->arrayKey, $other)) { 
      return false; 
     } 

     $this->value = $other[$this->arrayKey]; 

     return $this->constraint->evaluate($other[$this->arrayKey]); 
    } 

    /** 
    * @param mixed $other The value passed to evaluate() which failed the 
    *       constraint check. 
    * @param string $description A string with extra description of what was 
    *        going on while the evaluation failed. 
    * @param boolean $not Flag to indicate negation. 
    * @throws PHPUnit_Framework_ExpectationFailedException 
    */ 
    public function fail($other, $description, $not = FALSE) 
    { 
     parent::fail($other[$this->arrayKey], $description, $not); 
    } 


    /** 
    * Returns a string representation of the constraint. 
    * 
    * @return string 
    */ 
    public function toString() 
    { 
     return 'the value of key "' . $this->arrayKey . '"(' . $this->value . ') ' . $this->constraint->toString(); 
    } 


    /** 
    * Counts the number of constraint elements. 
    * 
    * @return integer 
    */ 
    public function count() 
    { 
     return count($this->constraint) + 1; 
    } 


    protected function customFailureDescription ($other, $description, $not) 
    { 
     return sprintf('Failed asserting that %s.', $this->toString()); 
    } 

它可用於這樣的:

... ->with(new Test_Constraint_ArrayHas($this->equalTo($value), $key)); 
+2

對該功能的請求:https://github.com/sebastianbergmann/phpunit/pull/312 – cweiske 2011-12-07 17:35:02

-2

對不起,我不是英語的人。

我認爲你可以測試一個鍵與array_key_exists功能數組中存在,如果有array_search

例如存在的價值,你可以測試:

function checkKeyAndValueExists($key,$value,$arr){ 
    return array_key_exists($key, $arr) && array_search($value,$arr)!==false; 
} 

使用!==因爲array_search返回該值的密鑰,如果存在,它可能是0.

+6

我知道所有這些,但我想在PHPUnit中設置一個斷言。 – 2009-09-28 15:56:42

15

代替創建可重複使用的約束的類,我能夠使用PHPUnit中現有的回調約束斷言數組鍵的值。在我的使用案例中,我需要檢查模擬方法的第二個參數中的數組值(如果有人感興趣,可以使用MongoCollection::ensureIndex())。以下是我想出了:

$mockedObject->expects($this->once()) 
    ->method('mockedMethod') 
    ->with($this->anything(), $this->callback(function($o) { 
     return isset($o['timeout']) && $o['timeout'] === 10000; 
    })); 

callback constraint預計其構造函數調用,並簡單地評價過程中調用它。斷言通過或失敗的基礎是否可調用返回true或false。

對於一個大型項目,我肯定會推薦創建一個可重用的約束(如上面的解決方案)或請求將PR #312合併到PHPUnit中,但這只是一次性需要的訣竅。很容易看出回調約束對於更復雜的斷言是如何有用的。

+0

是否有可能在'callback'禁忌中放置'assert *'? – jjoselon 2017-06-02 19:58:52

30

$this->arrayHasKey('keyname');方法存在,但它的名字是assertArrayHasKey:你希望做的參數一些複雜的測試,也有有用的信息和比較

// In your PHPUnit test method 
$hi = array(
    'fr' => 'Bonjour', 
    'en' => 'Hello' 
); 

$this->assertArrayHasKey('en', $hi); // Succeeds 
$this->assertArrayHasKey('de', $hi); // Fails 
2

在的情況下,總有把斷言的選項在回調之內。

例如

$clientMock->expects($this->once())->method('post')->with($this->callback(function($input) { 
    $this->assertNotEmpty($input['txn_id']); 
    unset($input['txn_id']); 
    $this->assertEquals($input, array(
     //... 
    )); 
    return true; 
})); 

請注意,回調返回true。否則,它總是會失敗。