Gesetz von Demeter

Mariexshhx

Bekanntes Mitglied
Java:
@Test
@DisplayName("Ein Kunde bekommt eine Mail")
void test_1() {
  Kontakt kontakt = mock(Kontakt.class);
  when(kontakt.getMail()).thenReturn("foo@bar.de");
  Kunde kunde = mock(Kunde.class);
  when(kunde.getKontakt()).thenReturn(kontakt);
  Mailer m = new Mailer(List.of(kunde));
  int mailsSent = m.mail();
  assertEquals(1, mailsSent);
}
Kann mir jemand sagen an welcher Stelle das Gesetz von Demeter verletzt wird ? ich Denke bei when(kunde.getKontakt()).thenReturn(kontakt); weil man hier getkontakt mit mit kontakt aufruft der dann aber getMail aufruft und genau das ist doch verboten oder ?
Vielen dank im vorraus
 

KonradN

Super-Moderator
Mitarbeiter
Also an so einem Unit Test sowas abzulesen ist schwer, der Verstoß kann aus meiner Sicht im Mailer zu finden sein. Der Mailer hat als direkte Umgebung den Kunden. Aber er greift scheinbar direkt auf den Kontakt zu und dessen Email-Adresse. Das hat den Mailer aber nicht zu interessieren. Der Mailer sollte nur auf die direkte Umgebung zugreifen. Im Test baust Du also deutlich mehr auf, als nur den direkten Kunden.

Das ist aber - wie schon gesagt - so rein am Unit Test nur schwer ablesbar. Der Code ist evtl. schlicht schwer testbar. Das, was der Mailer macht, wäre ggf. aufteilbar, so dass da nur etwas direkt mit dem Kunden gemacht wird und weitere Dinge dann ausgelagert sind (die haben dann als direkte Umgebung den Kontakt). Das würde bedeuten:
a) separater Unit Test der einen Kunden mit Email-Adresse bekommt.
b) ggf. mocken eines entstehenden Aufrufs. Der bekommt einen Kontakt, aber der Kontakt hat halt keine Email-Adresse. Und es wird nur geprüft, dass ein Aufruf mit dem erstellten Kontakt gemacht wurde.

Das wäre so etwas meine Sicht darauf. Also ja - das Problem ist, dass der Kontakt vom Kunde Details haben muss damit der Mailer getestet werden kann. Aber der Verstoß liegt halt aus meiner Sicht mehr im Mailer als im Unit Test.
 

Mariexshhx

Bekanntes Mitglied
Also an so einem Unit Test sowas abzulesen ist schwer, der Verstoß kann aus meiner Sicht im Mailer zu finden sein. Der Mailer hat als direkte Umgebung den Kunden. Aber er greift scheinbar direkt auf den Kontakt zu und dessen Email-Adresse. Das hat den Mailer aber nicht zu interessieren. Der Mailer sollte nur auf die direkte Umgebung zugreifen. Im Test baust Du also deutlich mehr auf, als nur den direkten Kunden.

Das ist aber - wie schon gesagt - so rein am Unit Test nur schwer ablesbar. Der Code ist evtl. schlicht schwer testbar. Das, was der Mailer macht, wäre ggf. aufteilbar, so dass da nur etwas direkt mit dem Kunden gemacht wird und weitere Dinge dann ausgelagert sind (die haben dann als direkte Umgebung den Kontakt). Das würde bedeuten:
a) separater Unit Test der einen Kunden mit Email-Adresse bekommt.
b) ggf. mocken eines entstehenden Aufrufs. Der bekommt einen Kontakt, aber der Kontakt hat halt keine Email-Adresse. Und es wird nur geprüft, dass ein Aufruf mit dem erstellten Kontakt gemacht wurde.

Das wäre so etwas meine Sicht darauf. Also ja - das Problem ist, dass der Kontakt vom Kunde Details haben muss damit der Mailer getestet werden kann. Aber der Verstoß liegt halt aus meiner Sicht mehr im Mailer als im Unit Test.
ich habe leider keinen Code für die Klassen. Für mich wirkt aber die Klasse Kontakt irgendwie unnötig. Die getMail Methode könnte ja auch in Kunde stehen, dann brauch man auch dieses getKontakt nicht. Wirkt für mich wie ein Umweg...
 

Oben