nothingworksinc / ticketbeast

Back to the lesson videos:
https://course.testdrivenlaravel.com/lessons
552 stars 11 forks source link

disableExceptionHandling() does not disable it #10

Closed likeadeckofcards closed 7 years ago

likeadeckofcards commented 7 years ago

I don't know why but when I tried to implement the disableExceptionHandling function (even by copy the code in this repo to ensure no typos). I still get the response code instead of the actual exception.

Any thoughts or suggestions?

(BTW: Great course so far)

BertvanHoekelen commented 7 years ago

Did you actually put the following line in the function your testing?

$this->disableExceptionHandling();
likeadeckofcards commented 7 years ago

Yes I did. and nothing happened

rickbolton commented 7 years ago

I think I may have had this issue perhaps.

Have you put it in your TestCase.php file instead of adding it to the specific test file.

protected function disableExceptionHandling()
    {
        $this->app->instance(ExceptionHandler::class, new class extends Handler {
            public function __construct() {}
            public function report(Exception $e) {}
            public function render($request, Exception $e) {
                throw $e;
            }
        });
    }
likeadeckofcards commented 7 years ago

Here is my TestCase.php file:

<?php

use App\Exceptions\Handler;
use Symfony\Component\Debug\ExceptionHandler;

abstract class TestCase extends Illuminate\Foundation\Testing\TestCase
{
    /**
     * The base URL to use while testing the application.
     *
     * @var string
     */
    protected $baseUrl = 'http://localhost';

    /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

        return $app;
    }

    protected function disableExceptionHandling()
    {
        $this->app->instance(ExceptionHandler::class, new class extends Handler {
            public function __construct() {}
            public function report(Exception $e) {}
            public function render($request, Exception $e) {
                throw $e;
            }
        });
    }
}

Sample Test (can't remember which one it was originally used on):

/** @test */
    function cannot_purchase_more_tickets_than_remain() {
        $this->disableExceptionHandling();

        $concert = factory(Concert::class)->states('published')->create()->addTickets(50);

        $this->orderTickets($concert, [
            'email' => 'test@test.com',
            'ticket_quantity' => 53,
            'payment_token' => 'valid-payment-token',
        ]);

        $this->assertResponseStatus(422);
        $this->assertFalse($concert->hasOrderFor('test@test.com'));
        $this->assertEquals(0, $this->paymentGateway->totalCharges());
        $this->assertEquals(50, $concert->ticketsRemaining());
    }

output of running the test (It does run extremely slow...):

C:\Users\medeck\Downloads\php-7.1.0-Win32-VC14-x64\php.exe C:/xampp/htdocs-temp/ticketbeast/vendor/phpunit/phpunit/phpunit --configuration C:\xampp\htdocs-temp\ticketbeast\phpunit.xml --filter "/::cannot_purchase_more_tickets_than_remain( .*)?$/" PurchaseTicketsTest C:\xampp\htdocs-temp\ticketbeast\tests\features\PurchaseTicketsTest.php --teamcity
Testing started at 2:36 PM ...
PHPUnit 5.7.4 by Sebastian Bergmann and contributors.

Time: 1.44 seconds, Memory: 16.00MB

OK (1 test, 4 assertions)

Process finished with exit code 0
BertvanHoekelen commented 7 years ago

The test is running fine if it's says OK. The exception helper is to translate laravel's http status responses into exception's which help you debugging.

It changes this function into

public function render($request, Exception $e) {
    throw $e;
}
likeadeckofcards commented 7 years ago

Yes there were a few tests in the app that when you implemented this function it caused the test to break.

likeadeckofcards commented 7 years ago

Here is the output when I force the test to break:

C:\Users\medeck\Downloads\php-7.1.0-Win32-VC14-x64\php.exe C:/xampp/htdocs-temp/ticketbeast/vendor/phpunit/phpunit/phpunit --configuration C:\xampp\htdocs-temp\ticketbeast\phpunit.xml --filter "/::cannot_purchase_more_tickets_than_remain( .*)?$/" PurchaseTicketsTest C:\xampp\htdocs-temp\ticketbeast\tests\features\PurchaseTicketsTest.php --teamcity
Testing started at 2:43 PM ...
PHPUnit 5.7.4 by Sebastian Bergmann and contributors.

Expected status code 422, got 500.
Failed asserting that 500 matches expected 422.
Expected :422
Actual   :500
 <Click to see difference>

 C:\xampp\htdocs-temp\ticketbeast\vendor\laravel\framework\src\Illuminate\Foundation\Testing\Concerns\MakesHttpRequests.php:744
 C:\xampp\htdocs-temp\ticketbeast\tests\features\PurchaseTicketsTest.php:98

Time: 1.45 seconds, Memory: 16.00MB

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

Process finished with exit code 1
BertvanHoekelen commented 7 years ago

Yes, because some test rely on the exception handler throwing http responses. I will search the course where Adam explains it. @adamwathan explains it in Getting Started with Validation Testing

By default the exception handler will try and change an exception that is thrown to an http response which the browser understand. For example ModelNotFoundException is automatically translated to a 404. But if you are testing your application it can be difficult to debug because the only response phpunit is getting is that 404. Adam's function disables this behaviour, which helps you see the stack trace that is originally thrown.

likeadeckofcards commented 7 years ago

If you look at the last test I pasted here it shows the response code still being sent back instead of re-throwing the exception like this method is supposed to prevent.

BertvanHoekelen commented 7 years ago

The method is supposed to re-throw (it disables the original method which translates it into http status codes). Try removing $this->disableExceptionHandling(); in the test.

adamwathan commented 7 years ago

Hey @infernobass7, your problem is you are overriding the wrong Exception Handler.

At the top of your test case file, you have:

use Symfony\Component\Debug\ExceptionHandler;

That should be:

use Illuminate\Contracts\Debug\ExceptionHandler;

Copy the full test case file from here and see if that helps:

https://github.com/nothingworksinc/ticketbeast/blob/master/tests/TestCase.php

BertvanHoekelen commented 7 years ago

Ah, I did not see that sorry! I was thinking that the ValidationException was thrown instead of the actual 422 that you were expecting. Luckily Adam is here to help :)

likeadeckofcards commented 7 years ago

Thank you, Adam. That was exactly what I was missing!

skinnyvin commented 6 years ago

Ha! This one got me too!