Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Spikerok's avatar

Howto Test delete method in Laravel 5.1

I have a method in controller that I would like to test

public function destroy(Instrument $instrument)
{
    $instrument->delete();
    
    flash()->success('Instrument Deleted Successfully!');

    return Redirect::route('instrument.index');
}

If I am to test controller manually method works fine.

However, I have been trying to test this without much luck... btw, this method is accessed via DELETE method.

Below are some example of calls that I have tried:

$this->action('DELETE', 'InstrumentController@destroy', ['id' => 19]);

And this..

$this->delete('/instrument/destroy/19');

I was trying to test using $this->visit() but when you click on delete button a bootstrap toolkit appears, because its not preloaded in the dom i am unable to test using $this->visit()...

If some one could help out, would be great

btw. In routes file controller class called using Route::resource

0 likes
5 replies
christopher's avatar

btw: where do you fetch the ID of your item to destroy in your method?

Should be something like this

public function destroy($id, Request $request, Instrument $instrument)
{
    /*
    * Get the id of the instrument  to delete
    */
    $instrument = $instrument->findOrFail($id);

    if($instrument->delete()){

        /*
         * Create success flash message
         */
        $request->session()->flash('success', '$message');

        return back();
    }
}
1 like
RachidLaasri's avatar

You just need to mock it and check if a delete method is called and same for the session you can check if it has a type of 'success' and message or 'Instrument Deleted Successfully!'.

Jeffberry's avatar

@christopher he appears to be using route model binding. The model instance is being injected into his controller instead of the ID.

When you do your test by calling the route with the DELETE method, does the resource actually get deleted from the database and you're just trying to verify that the delete worked? Or is the delete itself failing?

Spikerok's avatar

Yes, i do use route binding that handles FindOrFail for me.

when i use phpunit to delete database is not updated. when i perform action manually record is being deleted from the database

Mocking methods is something that i am considering right now or rather than having to use 'delete' method in routes to use 'get'.

In the present moment the solution that I have is below:

public function testDelete() {
        $this->withoutMiddleware();
        $response = $this->call('DELETE', '/instrument/20');
        $this->assertEquals(302, $response->getStatusCode());
        $this->notSeeInDatabase('instrument', ['deleted_at' => null, 'id' => 20]);
}

My test wasn't touching database due to test missing _token param.. initially i have tried using helper csrf_token() but csrf_token() keeps returning "null" so I had to use $this->withoutMiddleware(); to by pass the middleware check.

I am wondering if I am having issue with csrf_token() due to my setup method? at the moment I have code below:

public function setUp() {
        $this->refreshApplication();
        $this->faker = Faker\Factory::create('en_EN');

        $user = App\User::find(2);

        $this->be($user);
    }
Spikerok's avatar
Spikerok
OP
Best Answer
Level 2

The reason why I kept getting csrf_token() == null is due to incorrect setup in setUp method.

public function setUp() {
        parent::setUp(); // performs set up
        
        Session::start(); // starts session, this is what handles csrf token part
         
        $this->faker = Faker\Factory::create('en_EN');

        $user = App\User::find(2);

        $this->be($user);
    }

public function testDeleteMethod() {
        $response = $this->call('DELETE', '/instrument/20', ['_token' => csrf_token()]);
        $this->assertEquals(302, $response->getStatusCode());
        $this->notSeeInDatabase('instrument', ['deleted_at' => null, 'id' => 20]);
}
3 likes

Please or to participate in this conversation.