{ }
type
GraphQL · Magento · PHPUnit · Testing · Integrationstests
Magento GraphQL testen
PHPUnit, Integrationstests und echte Requests

Ungetestete GraphQL-Resolver sind eine Zeitbombe: Schema-Änderungen brechen Frontend-Verträge unbemerkt, Authentifizierungsfehler bleiben bis zum produktiven Einsatz verborgen. Dieser Artikel zeigt, wie man Magento GraphQL auf drei Ebenen testet – von Unit-Tests für Resolver-Logik bis zu echten HTTP-Requests gegen den Endpoint.

18 Min. Lesezeit PHPUnit · graphQlQuery() · Fixtures · Mocking · curl · Contract-Tests Magento 2.4 · PHP 8.x · PHPUnit 10+

1. Teststrategie: drei Ebenen für GraphQL-Resolver

GraphQL-Resolver in Magento können auf drei Ebenen getestet werden, die sich in Geschwindigkeit, Isolation und Aussagekraft unterscheiden. Unit-Tests sind schnell und isoliert, testen aber nur die interne Logik eines Resolvers ohne echten Datenbankzugriff. Integrationstests laufen im Magento-Framework-Kontext mit einer echten Testdatenbank und sind realistischer, aber deutlich langsamer. HTTP-Tests gegen den echten GraphQL-Endpoint sind am nächsten am Produktivbetrieb, erfordern aber eine laufende Magento-Instanz.

Eine sinnvolle Teststrategie kombiniert alle drei Ebenen: Unit-Tests für die Resolver-Logik und Service-Schicht, Integrationstests für die Verbindung zwischen Resolver, Repository und Schema, und mindestens ein HTTP-Test pro Query und Mutation als Smoke-Test im Deployment-Prozess. Wer nur eine Ebene testet – meistens fehlen Integrationstests – hat eine Lücke, die Magento-spezifische Fehler wie falsche di.xml-Konfigurationen oder Schema-Merge-Konflikte nicht aufdeckt.

2. Unit-Tests: Resolver-Logik ohne Magento-Framework

Magento-Resolver sollten so aufgebaut sein, dass ihre Logik ohne den gesamten Magento-Framework-Bootstrap testbar ist. Das bedeutet: Geschäftslogik in Services auslagern, die keine Magento-spezifischen Abhängigkeiten haben, und Resolver als dünne Delegationsschicht halten. Dann kann man den Service mit PHPUnit und einfachen Mock-Objekten testen, ohne eine Magento-Instanz zu starten.

In der Praxis scheitert das oft daran, dass Resolver direkt Repositories oder das ObjectManager-Muster verwenden, die schwer zu mocken sind. Der Schlüssel ist, Abhängigkeiten über den Konstruktor zu injizieren und Interfaces statt konkreter Klassen als Typen zu verwenden. Eine Resolver-Klasse, die ein CustomerBadgeServiceInterface injiziert bekommt, kann in Tests mit einer Mock-Implementierung dieses Interfaces getestet werden – schnell, präzise und ohne Framework-Overhead.


# The query under test — used in both integration tests and HTTP smoke tests
query CustomerBadgeTest {
  mironCustomerBadge(customer_id: 1) {
    badge_level
    points
    next_level_threshold
    expires_at
  }
}

# Mutation test example
mutation UpdateBadgeLevelTest {
  mironUpdateBadge(input: {
    customer_id: 1
    badge_level: "gold"
  }) {
    success
    message
    updated_badge {
      badge_level
      points
    }
  }
}

3. Integrationstests mit graphQlQuery()

Magento stellt für GraphQL-Integrationstests eine Basisklasse Magento\TestFramework\TestCase\GraphQlAbstract zur Verfügung, die die Methode graphQlQuery() und graphQlMutation() bereitstellt. Diese Methoden senden echte GraphQL-Requests gegen die Testinstanz, laden die Response und geben sie als PHP-Array zurück. Das ermöglicht präzise Assertions auf die exakte Response-Struktur, ohne curl-Commands schreiben zu müssen.

Integrationstests dieser Art laufen in der Testdatenbank von Magento, die für jeden Test-Run fresh aufgesetzt oder über Fixtures mit Daten befüllt wird. Sie sind deutlich langsamer als Unit-Tests – ein einzelner Integrationstest dauert oft 2–10 Sekunden –, aber sie prüfen genau das, was in der Praxis schiefgehen kann: falsche FQCN in di.xml, Schema-Merge-Konflikte, fehlende Berechtigungen und inkorrekte Response-Strukturen. Für jeden neuen Resolver sollte mindestens ein Integrationstest existieren, der den Happy-Path und einen Fehlerfall abdeckt.


# Integration test query — used with Magento's graphQlQuery() method
# Tests the full stack: schema → resolver → service → repository → database
query IntegrationTestProducts {
  products(
    filter: { sku: { eq: "test-product-001" } }
    pageSize: 1
  ) {
    total_count
    items {
      sku
      name
      price_range {
        minimum_price {
          final_price { value currency }
        }
      }
    }
  }
}

# Assert in PHPUnit:
# self::assertEquals(1, $response['products']['total_count'])
# self::assertEquals('test-product-001', $response['products']['items'][0]['sku'])
# self::assertNotEmpty($response['products']['items'][0]['price_range'])

4. Test-Fixtures: Testdaten sauber anlegen

Integrationstests brauchen konsistente Testdaten. Magento stellt dafür das Fixture-System mit @magentoDataFixture-Annotationen bereit. Eine Fixture-PHP-Datei legt Produkte, Kategorien, Kunden oder andere Entitäten in der Testdatenbank an und wird nach dem Test automatisch zurückgerollt. Das Magento-Framework nutzt Database-Rollback-Transaktionen, um die Testdatenbank nach jedem Test in den Ausgangszustand zurückzusetzen.

Für GraphQL-Resolver-Tests sind besonders Produkt- und Kunden-Fixtures wichtig. Produkt-Fixtures sollten alle Attribute setzen, die der Resolver zurückgibt – sonst liefern Tests positive Ergebnisse, weil null-Werte mit dem erwarteten Ergebnis übereinstimmen. Kunden-Fixtures müssen reale Kunden-Entitäten anlegen, nicht nur IDs, weil der Magento-Authentifizierungsstack den kompletten Kunden-Record benötigt. Gut geschriebene Fixtures sind deklarativ und kommentiert – sie beschreiben, welche Ausgangslage sie erzeugen, nicht wie sie es technisch tun.

5. Authentifizierte Queries testen

Queries und Mutationen, die einen authentifizierten Kunden erfordern, müssen mit einem Bearer-Token getestet werden. In Integrationstests stellt Magento die Methode graphQlQuery($query, [], '', ['Authorization' => 'Bearer ' . $token]) zur Verfügung. Den Token erhält man über eine Mutation generateCustomerToken oder direkt über den Token-Service. Für Integrationstests, die einen Kunden benötigen, ist die Kombination aus Kunden-Fixture und Token-Generierung der Standardweg.

Besonders wichtig ist es, auch den negativen Fall zu testen: Was passiert, wenn eine Query, die einen authentifizierten Kontext erfordert, ohne Token aufgerufen wird? Der Resolver sollte mit einer GraphQlAuthorizationException antworten, die sich im errors-Array der Response zeigt. Dieser Test prüft, ob die Sicherheitsprüfung tatsächlich implementiert ist – und nicht nur die positive Variante, was ein häufiger Test-Blindspot ist.

6. Fehlerszenarien und Exception-Typen testen

Fehlerszenarien zu testen ist mindestens genauso wichtig wie den Happy-Path zu testen. Für GraphQL-Resolver gibt es drei typische Fehlerklassen, die jeweils explizit getestet werden sollten: Eingabefehler (ungültige Argumente, fehlende Pflichtparameter), nicht gefundene Entitäten (Produkt-ID existiert nicht) und Autorisierungsfehler (Zugriff ohne Token oder mit falschem Scope). Jeder dieser Fälle sollte zu einer spezifischen Exception-Klasse führen, die Magento in eine strukturierte GraphQL-Fehlermeldung umwandelt.

In Integrationstests fängt man diese Fehler über die expectException()-Methode von PHPUnit ab oder prüft das errors-Array der Response, wenn der Test die Response trotz Fehler weiterverarbeiten soll. Letzteres ist sinnvoll, wenn man die genaue Fehlermeldung und Kategorie testen möchte: self::assertEquals('graphql-authorization', $response['errors'][0]['category']). Diese Präzision stellt sicher, dass Frontends auf definierte Fehlerstruktur vertrauen können.

7. Testarten im Vergleich

Jede Testart hat ihre spezifische Rolle in der GraphQL-Teststrategie. Die Auswahl der richtigen Testart für den richtigen Zweck verhindert sowohl übermäßig lange Test-Runs als auch Testlücken.

Testart Geschwindigkeit Was wird geprüft Was wird nicht geprüft
Unit-Test (PHPUnit) < 100 ms Resolver-Logik, Service-Methoden, Datenvalidierung Schema, di.xml, Datenbankabfragen
Magento-Integrationstest 2–10 s Schema, Resolver, Repository, Authentifizierung HTTP-Stack, Varnish-Caching, Lastverhalten
HTTP-Smoke-Test (curl) 0.5–2 s Endpoint-Verfügbarkeit, HTTP-Stack, Response-Format Edge-Cases, Datenkorrektheit, Fehlerszenarien
Contract-Test variabel Schema-Kompatibilität mit Frontend-Queries Datenbankinhalt, Performance, Authentifizierung
Load-Test (k6, JMeter) Minuten Performance unter Last, Caching-Verhalten Fachliche Korrektheit, Error-Cases

8. Echte HTTP-Requests: curl und Postman

Für schnelle manuelle Tests und als Deployment-Smoke-Test eignen sich echte HTTP-Requests mit curl oder Postman. Ein einfacher curl-Aufruf gegen den GraphQL-Endpoint zeigt sofort, ob der Endpoint erreichbar ist, ob das Schema die eigene Query kennt und ob die Response die erwartete Struktur hat. Dieser Test kann direkt im Deployment-Skript als letzter Schritt eingebaut werden und verhindert, dass eine fehlerhafte Konfiguration unbemerkt in die Produktion gelangt.

Postman ermöglicht darüber hinaus das Speichern und Versionieren von Query-Sammlungen, die das gesamte GraphQL-Modul dokumentieren und gleichzeitig als manuelle Testbasis dienen. In Kombination mit Postman-Environments kann dieselbe Query-Sammlung gegen Entwicklung, Staging und Produktion ausgeführt werden. Für Teams ist das eine pragmatische Methode, GraphQL-Dokumentation und Tests zu kombinieren, ohne ein separates Tool einführen zu müssen.


# HTTP smoke test queries — run these with curl after every deployment

# 1. Verify endpoint is up and schema is valid
# curl -X POST https://shop.example.com/graphql \
#   -H 'Content-Type: application/json' \
#   -d '{"query":"{ __typename }"}'

# 2. Verify custom query is registered
query SmokeTestCustomQuery {
  mironCustomerBadge(customer_id: 1) {
    badge_level
    points
  }
}

# 3. Verify authenticated query with Bearer token
# curl -X POST https://shop.example.com/graphql \
#   -H 'Content-Type: application/json' \
#   -H 'Authorization: Bearer <customer-token>' \
#   -d '{"query":"{ customer { firstname email } }"}'

# 4. Verify error response structure for unauthorized access
query VerifyAuthError {
  customer {
    firstname
  }
}
# Expected: errors[0].category = "graphql-authorization"

9. Contract-Tests: Frontend-Verträge sichern

Contract-Tests prüfen, ob das aktuelle GraphQL-Schema noch mit den Queries kompatibel ist, die das Frontend verwendet. Das Grundprinzip: die Frontend-Queries werden als GraphQL-Dokumente gespeichert und regelmäßig gegen das aktuelle Schema validiert. Wenn eine Schema-Änderung ein Feld entfernt oder umbenennt, das eine Frontend-Query verwendet, schlägt der Contract-Test fehl – bevor die Änderung deployed wird.

GraphQL Inspector ist ein praktisches CLI-Tool für diesen Zweck: graphql-inspector validate schema.graphql queries/*.graphql validiert alle gespeicherten Queries gegen das aktuelle Schema. In einer CI/CD-Pipeline, die nach jedem Merge ausgeführt wird, verhindert das unbeabsichtigte Breaking Changes. Für Magento-Projekte mit mehreren Frontends – etwa ein PWA-Frontend und eine mobile App – ist diese Praxis besonders wertvoll, weil Schema-Änderungen sonst beide Clients gleichzeitig brechen können.

10. Zusammenfassung

Eine vollständige Teststrategie für Magento GraphQL kombiniert Unit-Tests für Resolver-Logik und Services, Integrationstests mit graphQlQuery() für den vollständigen Stack, HTTP-Smoke-Tests für Deployment-Verifikation und Contract-Tests für Schema-Kompatibilität. Jede Ebene hat ihre spezifische Stärke und deckt Fehler ab, die die anderen Ebenen nicht sehen.

Der häufigste Fehler in Magento-Projekten: es gibt Unit-Tests für Services, aber keine Integrationstests für Resolver. Dadurch bleiben Konfigurationsfehler in di.xml, falsche FQCN-Angaben und Schema-Merge-Konflikte unentdeckt. Ein einziger Integrationstest pro Resolver – Happy-Path und ein Fehlerfall – erhöht das Vertrauen in Deployments erheblich und macht Refactoring sicherer.

Magento GraphQL Testing — Das Wichtigste auf einen Blick

Unit-Tests

Resolver-Logik und Services isoliert testen. Abhängigkeiten über Interfaces injizieren, damit Mocks möglich sind. Schnell und präzise für Logikfehler.

Integrationstests

GraphQlAbstract und graphQlQuery() für echte Stack-Tests mit Testdatenbank. Pflicht für jeden neuen Resolver – mindestens Happy-Path + Fehlerfall.

HTTP-Smoke-Tests

curl oder Postman nach jedem Deployment. Prüfen Endpoint-Verfügbarkeit, Schema-Validität und Response-Format im laufenden Betrieb.

Contract-Tests

GraphQL Inspector validiert Frontend-Queries gegen aktuelles Schema. In CI/CD-Pipeline: verhindert Breaking Changes bevor sie deployed werden.

11. FAQ: Magento GraphQL testen

1Welche Basisklasse für GraphQL-Integrationstests?
Magento\TestFramework\TestCase\GraphQlAbstract – stellt graphQlQuery() und graphQlMutation() bereit, die echte Requests senden und Response als PHP-Array zurückgeben.
2Resolver ohne Magento-Datenbank testen?
Logik in einen Service auslagern, der ein Interface implementiert. Service mit PHPUnit mocken. Resolver bleibt eine dünne Delegationsschicht ohne eigene Logik.
3Was ist @magentoDataFixture?
PHPUnit-Annotation, die PHP-Dateien mit Test-Setup einbindet. Daten werden nach dem Test per Rollback-Transaktion zurückgesetzt – saubere Testdatenbank nach jedem Test.
4Wie teste ich eine Query mit Bearer-Token?
graphQlQuery($query, [], '', ['Authorization' => 'Bearer ' . $token]). Token über generateCustomerToken-Mutation oder Token-Service im Test erzeugen.
5Fehlenden Token korrekt testen?
Ohne Authorization-Header aufrufen, dann errors[0].category auf graphql-authorization prüfen. Oder expectException(GraphQlAuthorizationException::class).
6Was ist ein GraphQL Contract-Test?
Prüft ob Frontend-Queries mit dem aktuellen Schema kompatibel sind. GraphQL Inspector validiert gespeicherte Query-Dateien – schlägt fehl wenn Felder entfernt oder umbenannt wurden.
7Wie Integrationstests ausführen?
bin/magento dev:tests:run integration oder vendor/bin/phpunit -c dev/tests/integration/phpunit.xml. Separate Testdatenbank muss konfiguriert sein.
8Für jede Query einen eigenen Integrationstest?
Ja – mindestens Happy-Path + Fehlerfall. Bei komplexen Resolvern zusätzlich Edge-Cases und Validierungsregeln testen.
9Wie langsame Integrationstests vermeiden?
Fixtures minimal halten, keine übermäßigen Datenmengen anlegen, Testdatenbank in RAM-Disk. Integrationstests in separaten CI-Jobs parallel ausführen.
10Postman für Magento GraphQL-Tests nutzen?
Ja. Postman unterstützt GraphQL nativ. Collections exportieren und mit Newman in CI-Pipelines ausführen. Gut für Smoke-Tests und manuelle Exploratory-Tests.