2009-09-28 33 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。否则,它总是会失败。