1

I am running some HTTP tests in Laravel 5.4, mainly using the assertJson helper method with phpunit. When I run other tests on my models using assertEquals I usually get very good feedback about specifically which properties, fields, etc. are different than expected. However, the assertJson method only tells me that there are differences, but not what those differences are. For instance, let's say I have a route my/route that returns this JSON:

{
  "name": "test",
  "foo": "bar"
}

I might run this Laravel test:

$response = $this->get("my/route");

$response->assertJson([
    'name' => 'test',
    'foo' => 'baz',
]);

My test fails as expected. However, the resulting message is pretty unhelpful:

Failed asserting that an array has the subset Array &0 (
    'name' => 'test'
    'foo' => 'baz'
).

For a non-trivial example with larger response, it can get pretty annoying to try to figure out what is different between the JSON responses. Is there any way to view the specific differences between the expected and actual outputs, instead of just knowing that something is different between the two?

2
  • Will you JSON response be multidimensional? Commented Feb 16, 2017 at 22:38
  • @RossWilson Yes, probably. This is for all http testing in general, not one specific request, but I definitely have routes that return multidimensional JSON. Commented Feb 17, 2017 at 1:59

1 Answer 1

0

You could wrap your assertion in a try-catch and then if the assertion fails you'll be able to create a new message and throw a new exception.

/**
 * @test
 * @group new
 */
public function testExample()
{
    $response = $this->get('test');

    try {
        $expected = [
            'name' => 'test',
            'foo'  => 'barz',
        ];

        $response->assertJson($expected);
    } catch (\Exception $e) {

        $exporter = new \SebastianBergmann\Exporter\Exporter();

        $message = 'The following items we\'re expected to be different ' .
            $exporter->export($this->arrayRecursiveDiff($expected, $response->decodeResponseJson()));

        throw new \PHPUnit_Framework_ExpectationFailedException($message);
    }
}

public function arrayRecursiveDiff($array1, $array2)
{
    $return = [];

    foreach ($array1 as $key => $value) {
        if (is_array($array2) && array_key_exists($key, $array2)) {
            if (is_array($value)) {
                $recursiveDiff = $this->arrayRecursiveDiff($value, $array2[$key]);
                if (count($recursiveDiff)) {
                    $return[$key] = $recursiveDiff;
                }
            } else {
                if ($value != $array2[$key]) {
                    $return[$key] = $value;
                }
            }
        } else {
            $return[$key] = $value;
        }
    }

    return $return;
}

Please note the arrayRecursiveDiff method isn't fully tested, however, there are quite a few different examples floating around for how to compare multidimensional arrays.

Hope this helps!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.