Mittwoch, 17. Oktober 2007

Best Practice: TDD und JSF managed beans bei agilem Vorgehen

"Änderungen werden erwartet, sie sind willkommen!" Das ist eine zentraler Gedanke bei agilem Vorgehen.

Was aber bedeutet das für die Vorgehensweise bei der Software Entwicklung? TDD! Am Beispiel von JSF möchte ich kurz zeigen, welcher klassische Fehler immer wieder gemacht wird, welche Konsequenzen daraus enstehen und wie man es besser machen kann. Im folgenden geht es um dieses Beispiel:

public class ChangePasswordBean
{
   private String password, passwordRepeat;

   public String doChangePassword() {
      // ...
   }

   public String getPassword() {
      return password;
   }

   public void setPassword(String password) {
      this.password = password;
   }

   public String getPasswordRepeat() {
      return passwordRepeat;
   }

   public void setPasswordRepeat(String passwordRepeat) {
      this.passwordRepeat = passwordRepeat;
   }
}

1# Managed Bean's und deren Abhängigkeiten

Bei JSF werden properties und action's in Managed Bean's zusammengefasst. Of braucht man innerhalb der action Methoden eine Reference zu einem Manager oder einem Service, dem die Verarbeitung delegiert wird. Das ist nicht problematisch, aber wie macht man das, damit das Managed Bean auch ohne Container testbar bleibt?

Nicht gut ist das hier: (faces-config.xml)

<managed-bean>
   <managed-bean-name>changePasswordBean</managed-bean-name>
   <managed-bean-class>example.ChangePasswordBean</managed-bean-class>
   <managed-bean-scope>request</managed-bean-scope>
</managed-bean>

... in Verbindung mit folgender Implementierung:

public String doChangePassword() {
   UserManager.getInstance().changePassword(uid, password);
}

Besser ist, den UserManager per Dependency Injection zu setzen und dann zur Verarbeitung die bean-interne Referenz zu verwenden:

<managed-bean>
   <managed-bean-name>changePasswordBean</managed-bean-name>
   <managed-bean-class>example.ChangePasswordBean</managed-bean-class>
   <managed-bean-scope>request</managed-bean-scope>
   <managed-property>
      <property-name>userManager</property-name>
      <value>#{userManager}</value>
   </managed-property>
</managed-bean>

... in Verbindung mit folgender Implementierung:

public String doChangePassword() {
   this.userManager.changePassword(uid, password);
}

Somit kann man eine Unit Test statt einem Integrationstest schreiben. Der UserManager in diesem Beispiel kann mittels JMock im Unit Test injected werden um State und Behavior des ChangePasswordBean sicherzustellen.

Keine Kommentare: