Blog

Mocking von statischen Aufrufen

Jeroen van Erp

Jeroen van Erp

Aktualisiert Oktober 23, 2025
3 Minuten

Wie können Sie Methoden testen, die statische Methodenaufrufe enthalten? Vor dieser Frage stehen wir gerade, während wir an einer Anwendung arbeiten, deren Teile von einem anderen Entwicklerteam geschrieben wurden. Um einen Einblick in die Funktionalität und Qualität der Codebasis zu erhalten, schreiben wir JUnit-Tests. Ein Großteil des Codes ist jedoch davon abhängig, dass entweder der JSF FacesContext oder der Spring ApplicationContext verfügbar ist.

Es ist jedoch unmöglich, statische Methodenaufrufe wie FacesContext.getCurrentInstance() nachzuahmen. Wie können wir also diese Aufrufe außerhalb des Containers testen? Wir haben uns drei verschiedene Ansätze überlegt, aber jeder hat seine Vor- und Nachteile. Lassen Sie uns zunächst einen Blick auf diese drei Ansätze werfen... 1. Methode extrahieren Führen Sie in jeder Klasse eine Methode ein, die wie folgt aussieht:

protected FacesContext getFacesContext() {
  return FacesContext.getCurrentInstance();
}

Sie können dies in Ihrem Test ganz einfach simulieren, indem Sie die Klasse mit einer überschriebenen Methode erstellen, wie folgt:

FacesContext mockContext = EasyMock.createMock(FacesContext.class);
new MyObjectUnderTest() {
  protected FacesContext getFacesContext() {
  return mockContext;
  }
}

Profis

  • Einfaches Refactoring mit der Extraktionsmethode

Nachteile

  • Jede Menge Code-Duplizierung

2. Statische Hilfsklasse Unsere zweite Option ist die Einführung einer statischen Hilfsklasse, die die folgende Implementierung aufweist:

public class FacesContextHelper {
  private static FacesContext Kontext;
  public static FacesContext getCurrentFacesContext() {
  return context != null ? context : FacesContext.getCurrentInstance();
  }
  public static void setFacesContext(FacesContext facesContext) {
  context = facesContext;
  }
  public static void reset() {
  Kontext = Null;
  }
}

In einer Testklasse können wir nun einfach die folgende Zeile schreiben, um den FacesContext zu mocken:

FacesContextHelper.setFacesContext(EasyMock.createMock(FacesContext.class));

Profis

  • Keine wirklich schmerzhafte Code-Duplizierung
  • Einfaches Suchen und Ersetzen, um alle Aufrufe von FacesContext.getCurrentInstance() in FacesContextHelper.getCurrentFacesContext() zu konvertieren.

Nachteile

  • Vergessen Sie nie, reset() beim Abbruch Ihres Tests aufzurufen, um zu verhindern, dass ein anderer Test Ihr Mock aufgreift.
  • Es fühlt sich nicht richtig an, statische Setter-Methoden in Ihren Code zu schreiben , nur um ihn testen zu können. Kein OO-Ansatz?

3. OO Helper-Klasse Unsere dritte und letzte Option ist die Einführung einer Schnittstelle und Implementierung des FacesContextHelper:

public interface FacesContextHelper {
  FacesContext getCurrentFacesContext();
}
public class FacesContextHelperImpl implements FacesContextHelper {
  public FacesContext getCurrentFacesContext() {
  return FacesContext.getCurrentInstance();
  }
}

Wir müssen nun in jeder Klasse eine Instanz von FacesContextHelperImpl einfügen. Für dieses Beispiel verwenden wir in jeder Klasse eine geschützte Paketvariable. Es ist natürlich auch möglich, eine Setter-Methode zu verwenden. Für unsere Testfälle müssen wir nun einen neuen FacesContextHelper einführen:

public class MockFacesContextHelper implements FacesContextHelper {
  private FacesContext mockContext;
  public MockFacesContextHelper(FacesContext mockContext) {
  this.mockContext = mockContext;
  }
  public FacesContext getCurrentFacesContext() {
  return this.mockContext;
  }
}

In unseren Testfällen können wir den FacesContext nun ganz einfach wieder mockieren, indem wir das geschützte Feld package setzen:

someClazz.facesContextHelper = new MockFacesContextHelper(EasyMock.createMock(FacesContext.class));

Profis

  • Fühlt sich natürlicher und OO an als die statische Helferlösung

Nachteile

  • Sie müssen für jede Klasse, die den FacesContext benötigt, ein neues Feld einführen.

Das war's. Ich selbst bin immer noch im Zweifel, welche Methode das kleinere Übel ist, denn keine fühlt sich absolut richtig an. Was denken Sie, welche Methode halten Sie für besser? Habe ich vielleicht eine andere Möglichkeit übersehen?

Verfasst von

Jeroen van Erp

Contact

Let’s discuss how we can support your journey.