Schlagwort-Archive: Klassenvariablen

Zugriff auf private Instanzvariabeln mit PowerMock

Die letzten Artikel (Mocken von statischen Methoden und Mocken von Konstruktoren) handelten von den fortgeschrittenen Funktionen des Mocking-Frameworks PowerMock. Dieses Mal geht es um den Zugriff auf private Instanzvariablen. Das Vorgehen gilt analog auch für private Klassenvariablen und private Konstanten. Zur Verdeutlichung wieder ein kleines Beispiel:

public class PowerMockSampleInternalState {

  private Map<String, String> internalMap = new HashMap<String, String>();

  public void put(String key, String value) {
    internalMap.put(key, value);
  }

  public String get(String key) {
    return internalMap.get(key);
  }
}

In dem Beispiel gibt es nur Zugriff auf die interne Map über put- und get-Methoden. So kann z.B. die Größe und der Inhalt der Map nicht von außen abgefragt werden.

Bisher habe ich für diese Zugriff das Framework JUnit-addons verwendet. Der Charme von PowerMock liegt aus meiner Sicht aber darin, dass nur eine Bibliothek für das Mocken und den Zugriff auf private Variablen, Konstanten und Methoden verwendet werden muss. Zusätzlich ist es bei PowerMock nicht notwendig, den Zugriff auf private Variablen und Konstanten zu Casten und das Ganze noch mit try-catch oder throws zu umgeben.

Ein Test mit PowerMock und JUnit sieht dann z.B. so aus:

/**
 * @author 7droids.de (FA) <br>
 *         Sample class with use cases for the mocking lib Power Mock
 */
public class PowerMockSampleInternalStateTest {

  /**
   * Test method for
   * {@link PowerMockSampleInternalState#put(String, String)}
   */
  @Test
  public void verifyThatPutAddsOnlyOnce() {
    PowerMockSampleInternalState internalState = new PowerMockSampleInternalState();
    Map<String, String> map = Whitebox.getInternalState(internalState, "internalMap"); // 1
    assertTrue("Map is empty", map.isEmpty());
    internalState.put("key", "initial value");
    assertEquals("One element in map", 1, map.size());
    internalState.put("key", "other value");
    assertEquals("Still one element in map", 1, map.size());
    assertEquals("other value", internalState.get("key"));
  }
}

Der ganze elegante Zugriff auf die interne Map erfolgt in der Zeile 1. Das Framework übernimmt dabei das Casting der Variable und wirft auch keine störenden Exceptions.

Im nächsten Artikel geht es dann um das Mocken von privaten Methoden mit Hilfe von PowerMock.