Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Funktionale Tests mit WebTestCase

Funktionale Tests mit WebTestCase

~16 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026

Unit-Tests aus Kapitel 42 prüfen ISOLIERTE Logik – jetzt testen wir das ZUSAMMENSPIEL: eine ECHTE HTTP-Anfrage an /login, die durch Routing, Security UND Controller läuft.

Die WebTestCase-Basisklasse

tests/Controller/SecurityControllerTest.php
<?php

declare(strict_types=1);

namespace App\Tests\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class SecurityControllerTest extends WebTestCase
{
    public function testLoginSeiteLaedt(): void
    {
        $client = static::createClient();
        $client->request('GET', '/login');

        self::assertResponseIsSuccessful();
        self::assertSelectorExists('form');
    }
}

createClient() erzeugt einen simulierten HTTP-Client, der GEGEN eine TATSÄCHLICH gebootete Symfony-Anwendung testet (in der test-Umgebung aus Kapitel 4) – request() löst eine ECHTE Anfrage aus, die durch Routing (Kapitel 7), Security (Block 5) UND den Controller läuft.

Wichtige Assertions für funktionale Tests

  • assertResponseIsSuccessful() – Status-Code 2xx.
  • assertResponseStatusCodeSame(404) – ein KONKRETER Status-Code.
  • assertResponseRedirects('/login') – Weiterleitung zu einer bestimmten Route.
  • assertSelectorExists('form') – ein CSS-Selektor findet ein Element im gerenderten HTML.
  • assertSelectorTextContains('h1', 'Anmelden') – ein Element enthält bestimmten Text.

Ein Formular ausfüllen und absenden

public function testRegistrierungFunktioniert(): void
{
    $client = static::createClient();
    $crawler = $client->request('GET', '/register');

    $client->submitForm('Registrieren', [
        'registration_form[name]' => 'Test-Nutzer',
        'registration_form[email]' => 'test@example.com',
        'registration_form[plainPassword]' => 'sicheres-passwort-123',
    ]);

    self::assertResponseRedirects('/login');
}

submitForm('Registrieren', [...]) findet den Button mit dem Text "Registrieren" (übersetzt aus dem Submit-Button des Formulars), füllt die angegebenen Feldnamen (im Symfony-Forms-Format aus Kapitel 15: formular_name[feld_name]) und klickt ihn – SIMULIERT das echte Nutzerverhalten, EINSCHLIESSLICH des in Kapitel 18 gebauten CSRF-Tokens, der AUTOMATISCH im Formular enthalten und mit abgeschickt wird.

Einen eingeloggten Nutzer simulieren

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;

public function testGeschuetzteSeiteBrauchtLogin(): void
{
    $client = static::createClient();

    // Ohne Login: Weiterleitung zur Login-Seite
    $client->request('GET', '/projects');
    self::assertResponseRedirects('/login');

    // Mit simuliertem Login: erfolgreicher Zugriff
    $entityManager = static::getContainer()->get(EntityManagerInterface::class);
    $user = $entityManager->getRepository(User::class)->findOneBy(['email' => 'anna@example.com']);

    $client->loginUser($user);
    $client->request('GET', '/projects');
    self::assertResponseIsSuccessful();
}

loginUser() umgeht den TATSÄCHLICHEN Login-Formular-Prozess und authentifiziert den Test-Client DIREKT – schneller als jedes Mal das Login-Formular auszufüllen, wenn NICHT der Login-Prozess selbst getestet werden soll, sondern eine ANDERE, geschützte Seite.

static::getContainer(): Zugriff auf Services in Tests

getContainer() gibt Zugriff auf DENSELBEN Service Container aus Block 6 – in Tests praktisch, um z. B. direkt Testdaten über den EntityManagerInterface anzulegen, statt den kompletten Registrierungs-Workflow durchzuklicken.

Tipp: Faustregel für Block 7: Unit-Tests (Kapitel 42) für ISOLIERTE Geschäftslogik, funktionale Tests (dieses Kapitel) für KRITISCHE Nutzer-Workflows (Login, Registrierung, Zugriffskontrolle) – ein GESUNDES Projekt hat typischerweise DEUTLICH mehr Unit-Tests als funktionale Tests, da letztere langsamer sind.