Donnerstag, 28. Juni 2007

TheServerSide: Test Driven Development

Bei TDD, oder auch Test Driven Development genannt, geht es nicht primär ums Testen, sondern es geht um gute Programmierung! Genauer, wie schreibt man Code, der sich testen lässt.

Es gibt da mehrere Ansätze, ein Beispiel-Dependency Injection:

Schlecht!

public class MyServiceImpl implements ServiceInterface {
   private final TheOtherService theOtherService;
   public MyService() {
      this.theOtherService = new TheOtherServiceImpl();
   }

   public int doIt(String a) {
      return this.theOtherService.doSomething(a);
   }
   ...
}

Besser!

public class MyServiceImpl implements ServiceInterface {
   private final TheOtherService theOtherService;
   public MyService(TheOtherService theOtherService) {
      this.theOtherService = theOtherService;
   }
   ...
}

Nur um dass nochmal deutlich klarzustellen: TheOtherService ist ein Interface! Die eigentliche Implementierung wird durch den Konfigrationskontext "incjected", z.B. Spring der JUnit in Verbindung mit JMock.

Warum? loose coupling! Im zweiten Beipiel kann man zum Bespiel ein Mock Object per Dependency Injection im Unit Test übergeben und prüfen, ob und wie Methoden von der injected Klasse aufgerufen werden. So kann sichergestellt werden, dass die Implementierung von ServiceInterface den(die) Aufrufe von einem Dao, einer Message Queue, einem SOA Endpoint etc. durchführt.

Unit Test:

public class MyServiceTestCase extends MockObjectTestCase {
   public void testSomething() {
      Mock mock = new Mock(TheOtherService.class);
      ...
      ServiceInterface objectUnderTest = new MyServiceImpl(mock );
      objectUnderTest.doIt("foo.bar");
      mock.expects(once()).method("doSomething").with(eq(a))
         .will(returnValue(result1));
      ...
      }
      ...
}

Grundsätzlich gilt bei TDD der "red-green-refactor-mantra".Erst schreibt man einen Test, der wird zunächst mal failen (red). Dann schreibt man die Implementierung und lässt den Test erneut laufen. Jetzt sollte er passen (green). Bei jedem folgendem Refactoring sollten die Tests ohne Modifikation immer "green" sein!

Ein ständiger red-green-red-green Lifecylce ist nicht die Idee!

Keine Kommentare: