Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
de:modul:ffit:3-jahr:cicd:learningunits:lu06:a [2026/03/15 17:03] apeterde:modul:ffit:3-jahr:cicd:learningunits:lu06:a [2026/03/15 18:28] (aktuell) apeter
Zeile 2: Zeile 2:
  
 Test Doubles sind Hilfsobjekte, Abhängigkeiten zu ersetzen und so Bereiche testen zu können, ohne, dass produktive, externe (bzw. ausserhalb des eigenen Testbereichs liegende) Systeme dafür benutzt werden müssen. Test Doubles sind Hilfsobjekte, Abhängigkeiten zu ersetzen und so Bereiche testen zu können, ohne, dass produktive, externe (bzw. ausserhalb des eigenen Testbereichs liegende) Systeme dafür benutzt werden müssen.
 +In der folgenden Tabelle ist eine kleine Übersicht über verschiedene Test Doubles in aufsteigender Reihenfolge. Es ist grundsätzlich empfohlen, die einfachste (oberste) Variante zu wählen, die funktioniert.
  
-Kleine Übersicht über verschiedene Test Doubles: +^ Double-Typ ^ Beschreibung ^ Entscheidungsfrage ^ 
-  Dummy Platzhalter +Dummy Platzhalter | Brauche ich nur ein Objekt? | 
-  Stub feste Antworten liefern +Stub | Vordefinierte Antworten | Welchen Wert soll zurückkommen? | 
-  Fake vereinfachte echte Implementierung +Fake | Vereinfachte echte Implementierung | Kann ich eine einfache echte Version bauen? | 
-  Spy Aufrufe beobachten +Spy Aufrufe beobachten | Brauche ich Zusatzcode, um etwas zu beobachten? | 
-  Mock erwartete Aufrufe überprüfen+Mock | Überprüfung direkt bei Aufruf | Ist es sinnvoll, den Test bereits abzubrechen? |
  
 ==== Dummy ==== ==== Dummy ====
Zeile 30: Zeile 31:
  
 Dadurch ist ein ''Stub'' im Prinzip wie eine Tabelle, in welcher zu einem bestimmten erwarteten Input der entsprechenden Output nachgeschlagen wird. Dadurch ist ein ''Stub'' im Prinzip wie eine Tabelle, in welcher zu einem bestimmten erwarteten Input der entsprechenden Output nachgeschlagen wird.
-<code javascript></code>+ 
 +<code javascript> 
 +const userRepositoryStub = { 
 +  findUserById(id) { 
 +    return { id: 1, name: "Alice"
 +  } 
 +
 + 
 +const service = new UserService(userRepositoryStub) 
 + 
 +const user = service.getUser(1) 
 +</code> 
 +In diesem Beispiel wird für die Id 1 immer das Alice-Testobjekt zurückgegeben, auch wenn die Datenbank andere Werte hätte.
  
 ==== Fake ==== ==== Fake ====
 Ein ''Fake'' ist eine vereinfachte Implementierung. Zum Beispiel wird eine Heuristik oder sonst eine schnelle Abkürzung verwendet. Ein ''Fake'' ist eine vereinfachte Implementierung. Zum Beispiel wird eine Heuristik oder sonst eine schnelle Abkürzung verwendet.
  
-Oft ersetzen Fakes in Tests Services wie Datenbanken mit einer einfacheren In-Memory-DB. +<code javascript> 
-<code javascript></code>+class FakeUserRepository { 
 +  constructor() { 
 +    this.users = new Map() 
 +  } 
 + 
 +  save(user) { 
 +    this.users.set(user.id, user) 
 +  } 
 + 
 +  findUserById(id) { 
 +    return this.users.get(id) 
 +  } 
 +
 + 
 +const repo = new FakeUserRepository() 
 +repo.save({ id: 1, name: "Alice" }) 
 + 
 +const service = new UserService(repo) 
 + 
 +expect(service.getUser(1).name).toBe("Alice"
 +</code> 
 +Wie auch in diesem Beispiel, ersetzen Fakes oft in Tests Services wie Datenbanken mit einer einfacheren In-Memory-DB. Die Objekte sind dadurch nur zur Laufzeit vorhanden, was aber für die Ausführung des Tests vollkommen ausreicht.
  
 ==== Spy ==== ==== Spy ====
 Ein ''Spy'' enthält Logik, um den Testverlauf zu überwachen. Zum Beispiel merkt er sich, wie oft oder mit welchen Argumenten eine Methode aufgerufen wurde. Ein ''Spy'' enthält Logik, um den Testverlauf zu überwachen. Zum Beispiel merkt er sich, wie oft oder mit welchen Argumenten eine Methode aufgerufen wurde.
-<code javascript></code>+ 
 +Es ist auch möglich, dass der Spy die echte Logik zusätzlich aufruft. 
 +<code javascript> 
 +class EmailServiceSpy { 
 +  constructor() { 
 +    this.callCount = 0 
 +    this.messages = [] 
 +  } 
 + 
 +  sendEmail(message) { 
 +    this.callCount++ 
 +    this.messages.push(message) 
 +  } 
 +
 + 
 +class UserService { 
 +  constructor(emailService) { 
 +    this.emailService = emailService 
 +  } 
 + 
 +  registerUser(email) { 
 +    this.emailService.sendEmail("Welcome " + email) 
 +  } 
 +
 + 
 +const emailSpy = new EmailServiceSpy() 
 +const service = new UserService(emailSpy) 
 + 
 +service.registerUser("alice@test.com"
 + 
 +if (emailSpy.callCount !== 1) { 
 +  throw new Error("Email should be sent exactly once"
 +
 + 
 +if (emailSpy.messages[0] !== "Welcome alice@test.com") { 
 +  throw new Error("Wrong email content"
 +
 +</code>
  
 ==== Mock ==== ==== Mock ====
 Ein ''Mock'' beinhaltet Logik, um die Eingabe oder den Zustand zum Zeitpunkt des Aufrufs zu überprüfen. Im Fehlerfall wird der Test abgebrochen, anstatt erst am Schluss die Überprüfungen zu machen. Ein ''Mock'' beinhaltet Logik, um die Eingabe oder den Zustand zum Zeitpunkt des Aufrufs zu überprüfen. Im Fehlerfall wird der Test abgebrochen, anstatt erst am Schluss die Überprüfungen zu machen.
-<code javascript></code>+<code javascript> 
 +class OrderService { 
 +  constructor(paymentGateway, repository) { 
 +    this.paymentGateway = paymentGateway 
 +    this.repository = repository 
 +  } 
 + 
 +  placeOrder(order) { 
 +    this.paymentGateway.authorize(order.amount) 
 + 
 +    this.repository.save(order) 
 + 
 +    this.paymentGateway.capture(order.amount) 
 +  } 
 +
 + 
 +class PaymentGatewayMock { 
 +  constructor() { 
 +    this.authorized = false 
 +  } 
 + 
 +  authorize(amount) { 
 +    if (this.authorized) { 
 +      throw new Error("authorize called twice"
 +    } 
 +    this.authorized = true 
 +  } 
 + 
 +  capture(amount) { 
 +    if (!this.authorized) { 
 +      throw new Error("capture called before authorize"
 +    } 
 +  } 
 +
 + 
 +const paymentMock = new PaymentGatewayMock() 
 + 
 +const repositoryStub = { 
 +  save() {} 
 +
 + 
 +const service = new OrderService(paymentMock, repositoryStub) 
 + 
 +service.placeOrder({ amount: 100 }) 
 +</code>
  • de/modul/ffit/3-jahr/cicd/learningunits/lu06/a.1773590605.txt.gz
  • Zuletzt geändert: 2026/03/15 17:03
  • von apeter