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?

netdjw
  • 5,419
  • 21
  • 88
  • 162

1 Answers1

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.

SEYED BABAK ASHRAFI
  • 4,093
  • 4
  • 22
  • 32