Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • Smarthome
  • Arduino
  • ESP32 & Co.
  • Raspberry Pi & Pico
  • Solo Mining
  • Über mich
  • Deutsch
  • English
Menu

Oracle Java: JUnit Testfall mit Mockito

Posted on 14. Februar 20193. Mai 2023 by Stefan Draeger

Mit dem Framework „Mockito“ kann man ein komplexes Objekt faken, bzw. Methoden und Objekte innerhalb einer Klasse nachbauen und für einen Testfall mit bestimmten Werten zurückgeben. Ganz nach dem Motto „Ich mocke mir die Welt, wie sie mir gefällt!“.

Erstellen eines Testprojektes in Eclipse

Erstellen wir uns für dieses Tutorial ein Testprojekt in der Entwicklungsumgebung Eclipse. Diese IDE kann unter https://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/2018-12/R/eclipse-jee-2018-12-R-win32-x86_64.zip heruntergeladen werden.

Hier nun ein leeres Eclipse Projekt mit allen benötigten Abhängigkeiten (dependencies) um dieses Tutorial durchzuarbeiten.

Oracle Java: JUnit Testfall mit MockitoHerunterladen

Einbinden von Mockito

Damit man das Framework „Mockito“ verwenden kann, muss man mindestens nachfolgende Abhängigkeit hinzufügen.

<dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-core</artifactId>
   <version>2.23.4</version>
   <scope>test</scope>
</dependency>

JUnit Testfall erzeugen

Mit Mockito kann man bestehende Testfälle erweitern, d.h. wir benötigen zusätzlich die Abhängigkeiten für JUnit. Für dieses Tutorial verwende ich JUnit4.

<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
</dependency>

<dependency>
   <groupId>org.hamcrest</groupId>
   <artifactId>hamcrest-core</artifactId>
   <version>2.1</version>
   <scope>test</scope>
</dependency>

Erzeugen wir uns zunächst einen einfachen Testfall.

Wir haben hier nun eine einfache innere Klasse „SimpleClass“ mit einem Feld „message“ vom Typ String, mit dem Inhalt „Hello World!“.

class SimpleClass{ 
   private String message = "Hello World!"; 

    public String getMessage() { return message; } 
    public void setMessage(String message) { this.message = message; } 
}

Nun können wir in der Methode „testSimpleClass“ testen, ob die Methode „getMessage“ im Standardfall den Text „Hello World!“ zurückliefert.

package de.draegerit.testmockito;

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class TestSimpleClass {

	
   @Test
   public void testSimpleClass() {
      SimpleClass s1 = new SimpleClass();
      assertEquals( "Hello World!", s1.getMessage());
   }
}

Nun können wir mit Mockito die Klasse „SimpleClass“ manipulieren so dass im Standardfall ein anderer Text zurückgeliefert wird.
Dazu müssen wir jedoch aus dieser Klasse in MockObjekt erzeugen.

Dieses können wir über eine Annotation machen, dann müssen wir jedoch zusätzlich vor dem Aufruf die Annotationen initialisieren. Dieses machen wir in einer Funktion welche mit @Before annotiert wurde. Diese „setup“ Funktion wird vor jedem Aufruf eines Testfalls in der TestKlasse ausgeführt.

@Mock
private SimpleClass simpleClass;
	
@Before
public void setup() {
   MockitoAnnotations.initMocks(this);
}
	
@Test
public void testSimpleClassMockAnnotation() {
   Mockito.when(simpleClass.getMessage()).thenReturn("Test123");
   assertEquals( "Hello World!", simpleClass.getMessage());
}

Möchte man das ganze etwas leichtgewichtiger machen, so kann man auch innerhalb der Funktion ein MockObjekt erzeugen:

@Test
public void testSimpleClassMock() {
   SimpleClass s1 = Mockito.mock(SimpleClass.class);
   assertEquals( "Hello World!", s1.getMessage());
}

Wenn wir nun die beiden Testfälle ausführen würden, so würde eine Exception auftreten.

JUnit Testfall mit Mockito - Fehlermeldung
JUnit Testfall mit Mockito – Fehlermeldung

Warum wird das Feld „message“ mit null initialisiert?
Das liegt daran, dass Mockito eine Hülle der Klasse erzeugt und die Felder zunächst mit den Standardeigenschaften erstellt. D.h. ein komplexer Datentyp wie java.lang.String wird mit null initialisiert, wenn wir diese Klasse mit der Funktion „mock“ oder Annotation „@Mock“ erzeugen.

Um hier die Standardimplementation der Klasse nutzen und testen zu können müssen wir die Klasse „SimpleClass“ statt mit einem „spy“ versehen.

@Spy
SimpleClass simpleClass;
	
@Before
public void setup() {
  MockitoAnnotations.initMocks(this);
}

Zusätzlich müssen wir die innere Klasse „SimpleClass“ in eine „public“ Class auslagern.

public class SimpleClass { 
   private String message = "Hello World!"; 
   
   public String getMessage() { return message; } 
   public void setMessage(String message) { this.message = message; } 
}

Nun können wir unseren Testfall auf die Funktion „getMessage“ ausprogrammieren und prüfen, ob die Funktion im Standardfall den Text „Hello World!“ zurückliefert.

@Test
public void test() {
  assertEquals( "Hello World!", simpleClass.getMessage());
}

Jedoch haben wir es selten mit so einfachen Testklassen Zutun.

Aufrufe prüfen

Mit Mockito kann man prüfen, ob eine Funktion auf einem MockObjekt ausgeführt wurde und zusätzlich definieren wie oft diese ausgeführt werden muss / sollte.

Nehmen wir an wir haben einen Datenbankservice, welcher uns eine Liste an Benutzer liefern soll. Wir wollen sicherstellen das dieser Service genau 1x eine Datenbankverbindung erstellt und dann die Benutzer lädt.

public class TestDatabaseAccess {

  @Spy
  private BenutzerDAO mockBenutzerDao;
	
  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
  }
	
  @Test
  public void testAccessDb() {
    mockBenutzerDao.findAll();
    Mockito.verify(mockBenutzerDao, Mockito.atLeast(1)).createConnection();
  }
}

Problem dabei ist, dass Mockito nur „public“ Methoden verarbeiten kann. D.h. wir müssen beim Design unserer Implementation darauf achten, dass wir dieses Testen können.

Im nachfolgenden testen wir einmal, ob das Hinzufügen von 3 Elementen zu der ArrayList geklappt hat.

package de.draegerit.testmockito;

import java.util.ArrayList;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import static org.mockito.Matchers.*;

public class TestList {

  @Spy
  private ArrayList<String> mockList;
	
  @Before
  public void setup() {
    MockitoAnnotations.initMocks(this);
  }
	
  @Test
  public void testAddEntry() {
    mockList.add("Test 1");
    mockList.add("Test 2");
    mockList.add("Test 3");
  	
    Mockito.verify(mockList, Mockito.atLeast(3)).add(anyString());
  }
}

Ebenso kann man auf dem gleichen Wege prüfen, ob diese Elemente wieder gelöscht wurden, d.h. ob die Funktion „remove“ mit irgendeinem Wert (anyInt) dreimal aufgerufen wurde.

@Test
public void testRemoveEntry() {
  mockList.add("Test 1");
  mockList.add("Test 2");
  mockList.add("Test 3");
		
  Mockito.verify(mockList, Mockito.atLeast(3)).add(anyString());
		
  mockList.remove(0);
  mockList.remove(0);
  mockList.remove(0);
		
  Mockito.verify(mockList, Mockito.atLeast(3)).remove(anyInt());		
	
}

Fertiges Projekt zum Download

Hier nun das gesamte Eclipseprojekt zum download.

Oracle Java: JUnit Testfall mit Mockito (fertiges Eclipse Projekt)Herunterladen

Fazit

Mit dem Framework Mockito kann man sich Objekte zum Testen erstellen und diese mit bestimmten Werten und Funktionen belegen. Dieses macht die Erstellung von umfangreichen Testfällen sehr einfach. Jedoch stößt man sehr schnell an die grenzen denn private & static Methoden lassen sich mit Mockito nicht testen bzw. mocken. Hier müsste man auf ein zusätzliches Framework wie EasyMock oder PowerMock zurückgreifen.

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Kategorien

Tools

  • Unix-Zeitstempel-Rechner
  • ASCII Tabelle
  • Spannung, Strom, Widerstand und Leistung berechnen
  • Widerstandsrechner
  • 8×8 LED Matrix Tool
  • 8×16 LED Matrix Modul von Keyestudio
  • 16×16 LED Matrix – Generator

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Technologien wie Cookies, um Geräteinformationen zu speichern und/oder darauf zuzugreifen. Wir tun dies, um das Surferlebnis zu verbessern und um personalisierte Werbung anzuzeigen. Wenn Sie diesen Technologien zustimmen, können wir Daten wie das Surfverhalten oder eindeutige IDs auf dieser Website verarbeiten. Wenn Sie Ihre Zustimmung nicht erteilen oder zurückziehen, können bestimmte Funktionen beeinträchtigt werden.
Funktional Immer aktiv
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Optionen verwalten Dienste verwalten Verwalten von {vendor_count}-Lieferanten Lese mehr über diese Zwecke
Einstellungen anzeigen
{title} {title} {title}