Test jednostkowy sprawdzający czy istnieje rekord w bazie

0

Witajcie,
Mam kod w Laravelu 6. Chciałbym napisać do tego Testy.

Mój kod wygląda następująco:

  1. Kontroler:

    public function destroy(Request $request)
        {
            if ($request->isMethod('post')) {
                foreach ($request->input('id') as $value) {
                    $this->model->delete($value);
                }
                return redirect()->route('ads.index')->with('success', 'Rekordy zostały usunięte!');
            }
        }
  1. Model:

    class Ad extends Model
    {
        use ScopeActiveTrait;
    
        protected $quarded = ['id'];
        protected $fillable = ['company_id', 'user_id', 'title', 'content', 'provincial_id', 'enable', 'url_address'];
        public $timestamps = true;
    
        public function author()
        {
            return $this->belongsTo('App\Models\User', 'user_id');
        }
    }
  1. Test:

    public function testDeleteAd()
        {
            $this->withExceptionHandling();
            //$this->withoutExceptionHandling();
            $user = User::find(1);
            $this->be($user);
    
            $ad = factory(Ad::class)->create();
            //$this->post(route('ads.destroy'), ['id[]' => $ads->toArray(), '_token' => csrf_token()]);
            //$response = $this->call('POST', route('ads.destroy'), ['_token' => csrf_token(), 'id[]' => $ads->toArray(), 'id' => $ads->toArray()]); dd($response);
            //$this->assertDatabaseMissing('ads', ['id' => $ads->id]);
    
            $ad = Ad::where('id', $ad->id)->first();
    
            $response = $this->post(route('ads.destroy'), [
                'id' => $ad->id,
                '_token' => csrf_token()
            ]);
            $this->assertDatabaseMissing('ads', ['id' => $ad->id]);
        }

Kiedy uruchamiam test otrzymuję błąd:

[email protected]:/var/www# vendor/bin/phpunit  --filter AdTest
PHPUnit 9.0.1 by Sebastian Bergmann and contributors.
 
F                                                                   1
/ 1 (100%)

Time: 1.83 seconds, Memory: 26.00 MB 
There was 1 failure:
1) Tests\Feature\AdTest::testDeleteAd Failed asserting that a row in
the table [ads] does not match the attributes {
     "id": 9 }.
 
 Found similar results: [
     {
         "id": 9,
         "company_id": 1,
         "user_id": 1,
         "title": "Dolore similique magnam tempora esse a ex ut excepturi.",
         "content": "Itaque animi fugit quod unde. Accusamus recusandae sit non quia cupiditate aspernatur. Sunt quas accusamus recusandae
 eius doloribus sequi.",
         "provincial_id": 2,
         "enable": "0",
         "url_address": "dolore-similique-magnam-tempora-esse-a-ex-ut-excepturi",
         "created_at": "2020-04-27 05:59:57",
         "updated_at": null
     } ].
 
 /var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithDatabase.php:45
 /var/www/tests/Feature/AdTest.php:71

W jaki sposób mogę to naprawić? Dlaczego wyskakuje tutaj błąd?
Rekord w bazie jest poprawnie utworzony, nie kasuje się i wyskakuje powyższy błąd

0

Z tego co zauważyłem, to używasz assertDatabaseMissing() która to sprawdza czy rekordu w bazie nie ma. Skoro mówisz że rekord w bazie jest utworzony to kod działa poprawnie. Może chciałeś użyć assertDatabaseHas()?

0
Adam Boduch napisał(a):

Z tego co zauważyłem, to używasz assertDatabaseMissing() która to sprawdza czy rekordu w bazie nie ma. Skoro mówisz że rekord w bazie jest utworzony to kod działa poprawnie. Może chciałeś użyć assertDatabaseHas()?

Chciałbym sprawdzić czy rekord został USUNIĘTY. Wydaje mi się że ten POST źle działa....
Jak testuje skrypt przez przeglądarkę, to wszystko działa poprawnie (metoda destroy poprawnie usuwa rekordy)

0

Analogicznie nie działa mi taki test:

public function testEditAdFromForm()
    {
        $user = User::find(1);
        $this->be($user);
        $faker = Faker\Factory::create('pl_PL');

        $ad = factory(Ad::class)->create();
        $id = $ad->id;

        $title = $faker->sentence($nbWords = 6, $variableNbWords = true);
        $response = $this->actingAs($user)->post(route('ads.edit').'/' . $id, [
            'title' => $title,
            'content' => $faker->text($maxNbChars = 200),
            'provincial_id' => $faker->numberBetween(1, 8),
            'id'=> $id
        ]);

        $this->assertDatabaseHas('ads', ['title' => $title, 'id' => $id]);
    }

zwraca błąd:
Failed asserting that a row in the table [ads] matches the attributes {
"title": "Amet dolores omnis autem consequatur quisquam temporibus.",
"id": 100
}.

0

Masz racje, źle przeczytałem post (kłania się czytanie ze zrozumieniem). Używasz debuggera jakiegoś? Mógłbyś sprawdzić co zwraca kontroler (stawiam na problem z autoryzacją użytkownika). Jeżeli nie masz debugera, to może w ten sposób będziesz w stanie sprawdzić:

dd($response->getContent());
0
Adam Boduch napisał(a):

Masz racje, źle przeczytałem post (kłania się czytanie ze zrozumieniem). Używasz debuggera jakiegoś? Mógłbyś sprawdzić co zwraca kontroler (stawiam na problem z autoryzacją użytkownika). Jeżeli nie masz debugera, to może w ten sposób będziesz w stanie sprawdzić:

dd($response->getContent());

Użytkownik o ID = 1 istnieje w bazie.
Wynik dla edycji: https://pastebin.com/yAjgNQit
Wynik dla kasowania: https://pastebin.com/Ya94867b

Nie wiem czy gdyby był problem z autoryzacją, to ten kod:


    public function testCreateAdFromForm()
    {
        $user = User::find(1);
        $this->be($user);
        $faker = Faker\Factory::create('pl_PL');
        $title = $faker->sentence($nbWords = 6, $variableNbWords = true);
        $response = $this->actingAs($user)->post(route('ads.store'), [
            'title' => $title,
            'content' => $faker->text($maxNbChars = 200),
            'provincial_id' => $faker->numberBetween(1, 8),
        ]);

        $this->assertDatabaseHas('ads', ['title' => $title]);
    }

też by nie działał.... A działa bez problemu

0

Wynik dla kasowania zwraca tyle kodu że nie mogę dopatrzeć się komunikatu błędu. Natomiast dla edycji komunikat jest, jak widzisz: The POST method is not supported for this route. Oznacza to, że wysyłasz żądanie POST natomiast w routes.php masz widocznie reguły jako GET.

0
Adam Boduch napisał(a):

Wynik dla kasowania zwraca tyle kodu że nie mogę dopatrzeć się komunikatu błędu. Natomiast dla edycji komunikat jest, jak widzisz: The POST method is not supported for this route. Oznacza to, że wysyłasz żądanie POST natomiast w routes.php masz widocznie reguły jako GET.

Dzięki, edycja mi działa poprawnie.Faktycznie był tam błąd. Kasowanie w dalszym ciągu nie działa, ale rout ma poprawny:

Route::post('/ads-destroy', 'cms\[email protected]')->name('ads.destroy')->middleware(['CheckRole:AdminMain'])->middleware('verified');

W PhpStorm w konsoli nie widzę więcej z tego debuga, niż to co wkleiłem ;/

0

Formularz który działa w przegląd∂arce wygląda tak:

<form novalidate method="post" action="http://cms.test/cms/ads-destroy" class="form-horizontal removeAction" id="removeAction">
<input type="hidden" name="_token" value="uhEn6O4tn0aAuvyvVa7yrx4gK9UJGPYevDPly5eV">
<input value="116" name="id[]" type="checkbox" class="icheckbox_square-red">
...
</form>

1 użytkowników online, w tym zalogowanych: 0, gości: 1