簡體   English   中英

PHPUnit:驗證數組是否具有具有給定值的鍵

[英]PHPUnit: Verifying that array has a key with given value

鑒於以下類:

<?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”的鍵,它的值為“Value 1”?

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

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

還有$this->contains('Value 1') ,可用於驗證數組是否具有此值。

我什$this->logicalAnd可以將這兩者與$this->logicalAnd結合起來。 但這當然不會給出預期的結果。

到目前為止,我一直在使用 returnCallback,捕獲整個 $params 然后對其進行斷言,但是也許有另一種方法可以做我想做的事?

$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

代替創建可重用的約束類,我能夠使用PHPUnit中現有的回調約束來聲明數組鍵的值。 在我的用例中,我需要在模擬方法的第二個參數中檢查數組值( MongoCollection :: ensureIndex() ,如果有人好奇的話)。 這是我想出的:

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

回調約束在其構造函數中期望有一個可調用的對象,並且在評估期間僅調用它。 根據可調用對象返回的是true還是false,斷言是通過還是失敗。

對於大型項目,我當然會建議創建一個可重用的約束(如上述解決方案中所述)或請求將PR#312合並到PHPUnit中,但這確實滿足了一次性需要。 很容易看出,回調約束對於更復雜的斷言也可能很有用。

我最終根據屬性一創建了自己的約束類

<?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));

如果您希望對參數進行一些復雜的測試,並獲得有用的消息和比較結果,則始終可以選擇在回調中放置斷言。

例如

$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。 否則,它將始終失敗。

如果您不介意在密鑰不存在(而不是失敗)時出現錯誤,那么您可以使用以下方法。

$this->assertEquals('Value 1', $params['key1']);

抱歉,我不會說英語。

我認為您可以使用array_key_exists函數測試數組中是否存在鍵,並且可以使用array_search測試值是否存在

例如:

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

使用!==因為array_search返回該值的鍵(如果存在),並且可以為0。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM