giorg's avatar
Level 1

test not working

Hi, I wrote these 2 tests that are not working:

public function testUpdate() {

        $deposit = factory(Deposit::class, 1)->create();

        $deposit->nome = 'armando';
        $this->post('deposits/' . $deposit[0]->id_deposito, $deposit[0]->toArray());

        $this->assertDatabaseHas('deposito',['id_deposito'=> $deposit[0]->id_deposito , 'nome' => 'armando']);
    }

    public function testDelete()
    {
        $deposit = factory(Deposit::class)->create();

        $this->get('deposits/' . $deposit->id_deposito . '/delete');

        $this->assertDatabaseMissing('deposito',['id_deposito'=> $deposit->id_deposito]);
    }

error i.e. in second case is: "Failed asserting that a row in the table [deposito] does not match the attributes { "id_deposito": 213 }"

but in my app I tried many times and it works perfectly. What am I doing wrong? Thanks a lot

0 likes
9 replies
aurawindsurfing's avatar

Hi @giorg

Looks like test is working but your code does not. You are not deleting the record from deposito table.

$this->assertDatabaseMissing('deposito',['id_deposito'=> $deposit->id_deposito]);

It looks like your delete route does not work as expected.

mstrauss's avatar

I haven't seen this to often, but it seems like in your successful test update method you post to an endpoint like:

this->post('deposits/' . $deposit[0]->id_deposito); 

Maybe you should be using the same endpoint when deleting, i.e. add the [0]:

$this->get('deposits/' . $deposit[0]->id_deposito . '/delete');
tykus's avatar

You assign a property on the Collection here, not on the model, this is why the assertion fails:

$deposit->nome = 'armando';

If you want to work with a single model instance, then use your factory to create one:

$deposit = factory(Deposit::class, 1)->create(); // returns a Collection
$deposit = factory(Deposit::class)->create(); // returns a Model instance

Here is the correct test implementation:

public function testUpdate() {
    $deposit = factory(Deposit::class)->create();
    $deposit->nome = 'armando';

    $this->post('deposits/' . $deposit->id_deposito, $deposit->toArray());
    
    $this->assertDatabaseHas('deposito',['id_deposito'=> $deposit[0]->id_deposito , 'nome' => 'armando']);
}

In the case of the delete scenario, you are making a GET request to destroy a resource, the correct implementation (assuming RESTful actions and you are not sift-deleting!) should be:

public function testDelete()
{
    $deposit = factory(Deposit::class)->create();

    $this->delete('deposits/' . $deposit->id_deposito . '/delete');

    $this->assertDatabaseMissing('deposito',['id_deposito'=> $deposit->id_deposito]);
}
giorg's avatar
Level 1

Thanks for all your answers, I modified the test this way:

public function testUpdate()
    {
        Auth::loginUsingId(8);

        $deposit = factory(Deposit::class)->create();

        $deposit->nome = 'armando';
        $response = $this->post('deposits/' . $deposit->id_deposito, $deposit->toArray());

        $response->assertStatus(200);

        $this->assertDatabaseHas('deposito', ['id_deposito' => $deposit->id_deposito, 'nome' => 'armando']);
    }

to be sure the route is fine, but in fact I get:

Expected status code 200 but received 405. Failed asserting that false is true.

but in my route.php I have:

Route::patch('deposits/{id}', 'DepositController@update');

so it should be fine... any further hint?

thanks again

tykus's avatar

You are sending a POST request to a route that expects a PATCH verb:

$this->post(...

change to:

$this->patch(...
2 likes
giorg's avatar
Level 1

thanks @tykus,

after changing that I now get "Expected status code 200 but received 419". After googling a bit I did put this at top of my test:

$this->withoutExceptionHandling();

which brought me to "1) Tests\Unit\DepositTest::testUpdate Illuminate\Session\TokenMismatchException:" and then a long trace, so I googled another bit, and added

use WithoutMiddleware;

now I get: "1) Tests\Unit\DepositTest::testUpdate InvalidArgumentException: Trailing data", but this time google don't help me...

thanks

tykus's avatar

That 419 response code is most likely a result of CSRF protection because you do not have a CSRF token in the request payload in the test. Disabling middleware is not the solution because although you can target a specific middleware to disable

$this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);

the middleware itself should already know that the app is running unit tests.

The question is why it does not know that it is running unit tests???

giorg's avatar
Level 1

good question. In my phpunit.xml I have:

<env name="APP_ENV" value="testing"/>

and I've read this overrides .env when testing, so I should be good to go...

giorg's avatar
Level 1

ok disabling the middleware leads to a 500: "[2019-07-23 15:37:43] local.ERROR: Trailing data {"userId":8,"exception":"[object] (InvalidArgumentException(code: 0): Trailing data at /Users/giorg/PhpstormProjects/aamscomm/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php:563)"

which I don't understand...

UPDATE:

must have something to do with the factory, because if I don't use the factory:

public function testUpdate()
    {
//        $this->withoutExceptionHandling();
        $this->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class);

        Auth::loginUsingId(8);

        $deposit = Deposit::findOrFail(255); //factory(Deposit::class)->create();

        $deposit->nome = 'armando';
        $response = $this->patch('deposits/' . $deposit->id_deposito, $deposit->toArray());

//        $response->assertStatus(200);

        $this->assertDatabaseHas('deposito', ['id_deposito' => $deposit->id_deposito, 'nome' => 'armando']);

        // dopo aver eliminato si è redirezionati alla lista
        $response->assertRedirect('/deposits');
    }

this is green. But I still don't get it, because also this one is green:

public function testCreate()
    {
        $count = Deposit::all()->count();

        factory(Deposit::class)->create();
        $countAfter = Deposit::all()->count();
        $this->assertEquals($count + 1, $countAfter);
    }

and definitely env is not testing, because I tried to set database sqlite and memory in phpunit.xml, but my createTest still writes on mysql db.

Please or to participate in this conversation.