Karptonite
Karptonite

Reputation: 1632

phpunit mock with partially known array expected: what are the correct constraints?

I'd like to create a mock in phpunit to verify that a function is being called with the correct parameter. The parameter is an associative array that contains three elements, two known, and one unknown:

array( 'objecttype' => 'thing', 'objectid'=> 2, 'tstamp' => [some tstamp here] )

Since I don't know the exact full array, I can't use the equalTo contraint. I could use a combination of logicalAnd, contains, and arrayHasKey to sort of get there, but that seems pretty hacky, and, if for some crazy reason my keys and values were mixed up, it wouldn't catch the error. Is there a better way to handle this?

Upvotes: 2

Views: 609

Answers (1)

David Harkness
David Harkness

Reputation: 36552

Here's a quick-and-dirty custom constraint to check that the passed array contains at least the given entries (key/value pairs). Add it to your custom testing framework or PHPUnit fork. Note that it uses == equality so that a key/mapping of '5' will match 5.

class ArrayHasEntries extends PHPUnit_Framework_Constraint
{
    /**
     * @var array
     */
    protected $array;

    /**
     * @param array $array
     */
    public function __construct(array $array)
    {
        $this->array = $array;
    }

    /**
     * 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
     */
    protected function matches($other)
    {
        foreach ($this->array as $key => $value) {
            if (!array_key_exists($key, $other) || $other[$key] != $value) {
                return false;
            }
        }
        return true;
    }

    /**
     * Returns a string representation of the constraint.
     *
     * @return string
     */
    public function toString()
    {
        return 'has the entries ' . PHPUnit_Util_Type::export($this->array);
    }

    /**
     * Returns the description of the failure
     *
     * The beginning of failure messages is "Failed asserting that" in most
     * cases. This method should return the second part of that sentence.
     *
     * @param  mixed $other Evaluated value or object.
     * @return string
     */
    protected function failureDescription($other)
    {
        return 'an array ' . $this->toString();
    }
}

Upvotes: 3

Related Questions