Unit-Testing: Exceptions testen

Möchte man das auftreten von Exceptions mit JUnit testen, so gibt es verschiedene Wege und Möglichkeiten. Die bekanntesten sind sicherlich

@Test(expected=IllegalArgumentException.class)
public void methodThrowsException() {
   subjectUnderTest.foo(someIllegalArgument);
}

und

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void methodThrowsException() {  
   thrown.expect(IllegalArgumentException.class);
   subjectUnderTest.foo(someIllegalArgument);
}

Beide Varianten haben den Nachteil, dass die Given-When-Then (oder Arrange-Act-Assert) Reihenfolge aufgebrochen wird, so dass man häufig „von Hand“ geschriebenen Code wie den folgenden findet:

@Test
public void methodThrowsException() {
   try {
      subjectUnderTest.foo(someIllegalArgument);
      fail("IllegalArgumentException expected, but not thrown!");
   } catch (IllegalArgumentException ex) {
      assertThat(ex.getMessage(), is("foobarfoo"));
   }
}

Jetzt sind die Anweisungen zwar wieder in der Given-When-Then Reihenfolge, aber die try-catch-Anweisungen machen den Code unübersichtlich.

Die folgende Lösung ist uns in den Sinn gekommen, nachdem wir uns im aktuellen Projekt über Clean Code ausgetauscht haben:

@Test
public void methodThrowsException() {
   IllegalArgumentException ex = foo(someIllegalArgument);
   assertThat(ex.getMessage(), is("foobarfoo"));
}

private Exception foo(FooBarFoo fooBarFoo) {
   try {
      subjectUnderTest.foo(someIllegalArgument);
      return null;
   } catch (IllegalArgumentException ex) {
      return ex;
   }
}

Der Testcode ist sauber, die Reihenfolge der Testanweisungen stimmt und es sind keine Erweiterungen wie @Rules oder catch-excpetion notwendig.

Veröffentlicht unter Blog | Verschlagwortet mit

Domain-Driven Design: First-Class Repositories

Unter anderem findet man in Vaughn Vernon Implementing Domain-Driven Design die Empfehlung das Repositories das Collection-Interface imitieren sollen:

public interface CargoRepository {
   add(Cargo cargo);
   remove(Cargo cargo);
   ...
}

Der Hintergedanke dabei ist, ein Repository nicht als DAO (Database Access Object) zu verstehen, sondern als fachlichen Behälter für aufzubewahrende Dinge – egal wie diese jetzt tatsächlich persistiert werden (Stichwort: persistence ignorance).

Aber warum nicht noch einen Schritt weiter gehen, und ein Repository als First-Class Collection betrachten:

public interface Cargoes {
   add(Cargo cargo);
   remove(Cargo cargo);
   ...
}

Dieser Gedanke kam mir beim Lesen von Jeff Bays Object Calisthenics. Mehr lässt sich Persistenz wohl nicht ignorieren…

Frohe Ostern

Allen Besuchern wünschen wir ein frohes Osterfest – und das der Frühling sich nicht länger hinter den Schneebergen versteckt.

Frohe Ostern

Weiße Ostern 2013

Dieses Foto entstand vor zwei Tagen in unserem Garten. Der Schnee liegt bei uns noch bis zu 10 Zentimeter hoch.