2

I have this test in my Laravel project:

// here are some test function configurations

// found nothing if not match
$this->post(action([TagController::class, 'search'], '!! Not foundable name !!'))
    ->assertOk()
    ->assertJsonCount(0, 'data');

// found it if match
$this->post(action([TagController::class, 'search'], $matchName))
    ->assertOk()
    ->assertJsonCount(1, 'data');

// found it if partly match
$this->post(action([TagController::class, 'search'], $partlyMatchName))
    ->assertOk()
    ->assertJsonCount(1, 'data');

Now I see this result if test failed:

Failed to assert that the response count matched the expected 0
Failed asserting that actual size 4 matches expected size 0.

This isn't say too mutch for me, I don't see which assertation failed and exactly why. I want to define custom message for this case.

I want to do someting like this:

->assertJsonCount(
    0,
    'data',
    'It should found noting, because of conditions are not match'
);

Is there any way to send custom message to the tester user in this case?

1 Answer 1

1

You should override decodeResponseJson() method of Illuminate\Testing\TestReponse class.

Create two classes of TestResponse and AssertableJsonString in Tests namespace as follows:

TestResponse

namespace Tests;

use Illuminate\Testing\Assert as PHPUnit;

class TestResponse extends \Illuminate\Testing\TestResponse
{
    /**
     * @inheritDoc
     */
    public function decodeResponseJson()
    {
        $testJson = new AssertableJsonString($this->getContent());

        $decodedResponse = $testJson->json();

        if (is_null($decodedResponse) || $decodedResponse === false) {
            if ($this->exception) {
                throw $this->exception;
            } else {
                PHPUnit::fail('Invalid JSON was returned from the route.');
            }
        }

        return $testJson;
    }
}

AssertableJsonString

namespace Tests;

use Illuminate\Testing\Assert as PHPUnit;

class AssertableJsonString extends \Illuminate\Testing\AssertableJsonString implements \ArrayAccess, \Countable
{
    /**
     * @inheritDoc
     */
    public function assertCount(int $count, $key = null, $message="Failed to assert that the response count matched the expected %d")
    {
        if (! is_null($key)) {
            PHPUnit::assertCount(
                $count, data_get($this->decoded, $key),
                sprintf($message, $count)
            );

            return $this;
        }

        PHPUnit::assertCount($count,
            $this->decoded,
            sprintf($message, $count)
        );

        return $this;
    }
}

Now, you need to bind Laravel TestResponse class to your custom TestResponse in boot method of AppServiceProvider as follows:

public function boot()
{
    $this->app->bind(\Illuminate\Testing\TestResponse::class,\Tests\TestResponse::class);
}

Notice: You need to place %d in your message format to be replaced by sprintf() function.

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

2 Comments

Sounds good, but I'm looking for a Laravel or PHPUnit built-in way.
As the message is hardcoded, I don't think there is a way to achieve this in laravel way at the moment.

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.