[JAVA] Ordnungsgemäße Verwendung von Mockito und PowerMock

Ich habe versucht, die ordnungsgemäße Verwendung von Mockito und PowerMock zu organisieren, wenn ich beim Testen mit JUnit mit Spring Boot verschiedene Methoden verspottete.

Zum Testen erforderliche Einstellungen

build.gradle


dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile group: 'org.powermock', name: 'powermock-api-mockito', version: '1.6.6'
    testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.6.6'
}

Fügen Sie einfach den Spring-Boot-Starter-Test ein und Sie können die folgenden zwei Bibliotheken verwenden. Die Version ist ** Spring-Boot-Gradle-Plugin: 1.5.2.RELEASE **.

Fügen Sie eine Einstellung hinzu, um das Power Mock zu verwenden, das später verwendet wird.


Klasse zur Erklärung verwendet

Zu testende Klasse

TestTargetClass.java


@Component
public class TestTargetClass {
  @Autowired
  private TestSubClass testSubClass;

  private String private_method() {
    return "private_method called " + private_sub();
  }

  private String private_sub() {
    return "private_sub";
  }

  public String public_method() {
    return "public_method called " + public_sub();
  }

  public String public_sub() {
    return "public_sub";
  }

  public String public_method_call_private_method() {
    return "public_method called " + private_sub();
  }

  public static String static_method() {
    return "static_method";
  }

  public String public_subclass_public_method() {
    return "public_subclass_method called " + testSubClass.sub_public_method();
  }

  public String public_subclass_private_method() {
    return "public_subclass_method called " + testSubClass.sub_public_method_call_private_method();
  }
}

Zu testende Unterklasse (Unterklasse DI aus der übergeordneten Klasse)

TestSubClass.java


@Component
public class TestSubClass {

  public String public_field = "public_field";
  private String private_field = "private_field";

  private String sub_private_method() {
    return "subclass_private_method has " + private_field;
  }

  public String sub_public_method() {
    return "subclass_public_method has " + public_field;
  }

  public String sub_public_method_call_private_method() {
    return "subclass_public_method called " + sub_private_method();
  }
}

Zuerst aus dem Basistest

Sie können Mockito für diese Testklasse verwenden.

RealTest.java


@RunWith(SpringRunner.class)
@SpringBootTest
public class RealTest {
  @Autowired
  private TestTargetClass instance;

  @Test
öffentliche Leertestmethode() {
    .....
  }
}

Testen des tatsächlichen Verhaltens öffentlicher Methoden

Unnötig zu schreiben, hier ist der Testcode

  @Test
public void kann durch Aufrufen öffentlicher Methoden getestet werden() {
    assertThat(public_method(), is("public_method called public_sub"));
  }

Testen des tatsächlichen Verhaltens privater Methoden

OK, wenn Sie setAccessible mit Reflektion verwenden

  @Test
public void Kann durch Aufrufen privater Methoden getestet werden() throws Exception {
    Method method = TestTargetClass.class.getDeclaredMethod("private_method");
    method.setAccessible(true);
    assertThat((String) method.invoke(instance), is("private_method called private_sub"));
  }

Testen des tatsächlichen Verhaltens statischer Methoden

Unnötig zu schreiben, hier ist der Testcode

  @Test
public void Kann durch Aufrufen statischer Methoden getestet werden() {
    assertThat(TestTargetClass.static_method(), is("static_method"));
  }

Hier ist der Test mit dem Mock des Hauptthemas.


Tests, die nur mit Mockito durchgeführt werden können

Beim Verspotten einer öffentlichen Methode

Verwenden Sie in solchen Fällen Mockito.mock ().

  @Test
public void Sie können öffentliche Methoden verspotten() {
    TestTargetClass mockInstance = mock(TestTargetClass.class);
    when(mockInstance.public_method()).thenReturn("mocked_public_method");
    assertThat(mockInstance.public_method(), is("mocked_public_method"));
  }

Beim Verspotten einer unteröffentlichen Methode, die von einer öffentlichen Methode aufgerufen wird

Ich möchte, dass die anderen Methoden als die Verspottungsmethode "public_sub ()" wie implementiert funktionieren. Verwenden Sie daher in solchen Fällen "Mockito.spy ()".

  @Test
public void Die von der public-Methode aufgerufene Sub-Methode kann mit Spy verspottet werden() {
    TestTargetClass mockInstance = spy(new TestTargetClass());
    when(mockInstance.public_sub()).thenReturn("mocked_public_sub");
    assertThat(mockInstance.public_method(), is("public_method called mocked_public_sub"));
  }

Tests, die mit PowerMock durchgeführt werden können

Die Testklasse bei Verwendung von PowerMock sieht folgendermaßen aus

@RunWith(PowerMockRunner.class)
@PrepareForTest({TestTargetClass.class})
public class PowerMockTest {
  @Test
öffentliche Leertestmethode() {
    .....
  }
}

Private Methode verspotten

Verwenden Sie "PowerMockito.mock ()" und "PowerMockito.when ()". Verwenden Sie außerdem "MemberMatcher.method ()", um eine private Methode anzugeben.

  @Test
public void private Methoden können mit PowerMockito verspottet werden() throws Exception {
    TestTargetClass mockInstance = PowerMockito.mock(TestTargetClass.class);
    PowerMockito.when(mockInstance, MemberMatcher.method(TestTargetClass.class, "private_method"))
                .withNoArguments().thenReturn("mocked_private_method");

    //Verwenden Sie Reflection, um auf private Methoden zuzugreifen
    Method method = TestTargetClass.class.getDeclaredMethod("private_method");
    method.setAccessible(true);

    assertThat((String) method.invoke(mockInstance), is("mocked_private_method"));
  }

Schein statische Methode

Verwenden Sie "PowerMockito.mockStatic ()" und "PowerMockito.when ()".


  @Test
Statische Methoden für öffentliche Leeren können mit PowerMockito verspottet werden()() {
    PowerMockito.mockStatic(TestTargetClass.class);
    PowerMockito.when(TestTargetClass.static_method()).thenReturn("mocked_static_method");
    assertThat(TestTargetClass.static_method(), is("mocked_static_method"));
  }

Beim Verspotten einer subprivaten Methode, die von einer öffentlichen Methode aufgerufen wird

Ich möchte, dass die anderen Methoden als die Verspottungsmethode "private_sub ()" wie implementiert funktionieren. Verwenden Sie daher in solchen Fällen "PowerMockito.spy ()" und "PowerMockito.when ()". Verwenden Sie außerdem "MemberMatcher.method ()", um eine private Methode anzugeben.

  @Test
public void Subprivate Methoden, die von öffentlichen Methoden aufgerufen werden, können mit Spion verspottet werden() throws Exception {
    TestTargetClass mockInstance = PowerMockito.spy(new TestTargetClass());
    PowerMockito.when(mockInstance, MemberMatcher.method(TestTargetClass.class, "private_sub"))
                .withNoArguments().thenReturn("mocked_private_sub");

    assertThat(mockInstance.public_method_call_private_method(),
        is("public_method called mocked_private_sub"));
  }

Wenn Sie eine Klasse verspotten, die DI in der Klasse ist

Es wird angenommen, dass die Serviceklasse DI in der Controller-Klasse verspottet ist. Zu diesem Zeitpunkt wird auch PowerMock verwendet. DI die Zielklasse von "@ Autowired", die in der durch "@ InjectMocks" in der Annotation "@ SpringBootTest" angegebenen Klasse angegeben ist. Die Zielklasse von "@ Autowired" ist "PowerMockito.spy ()" als Klassenvariable.


Die Testklasse sieht so aus

@RunWith(PowerMockRunner.class)
//PowerMock-Zielklasse
@PrepareForTest({TestSubClass.class})
@SpringBootTest
public class PowerMockSubclassTest {
  @InjectMocks
  private TestTargetClass instance;
  private TestSubClass testSubClass = PowerMockito.spy(new TestSubClass());

  @Test
öffentliche Leertestmethode() {
    .....
  }
}

Es scheint, dass Sie nicht verspotten können, selbst wenn Sie anstelle der Klassenvariablen Folgendes tun. ... Vielleicht Bitte kommentieren Sie, ob es einen guten Weg gibt.

  @Test
öffentliche Leertestmethode() {
     TestSubClass testSubClass = PowerMockito.spy(new TestSubClass());
  }

Verspotten Sie öffentliche Methoden von Unterklassen

Da es sich tatsächlich um eine öffentliche Methode handelt, ist der Teil, in dem die Unterklasse in der Testklasse deklariert ist, der

private TestSubClass testSubClass = PowerMockito.mock(TestSubClass.class);

Es ist in Ordnung, aber es kann nicht zusammen mit dem verwendet werden, der spy () in derselben Quelldatei verwendet, also werde ich es mit spy () vereinheitlichen. Verwenden Sie PowerMockito.when ().

  @Test
public void Kann öffentliche Methoden von Unterklassen verspotten() {
    PowerMockito.when(testSubClass.sub_public_method()).thenReturn("mocked_subclass_public_method");
    assertThat(instance.public_subclass_public_method(),
        is("public_subclass_method called mocked_subclass_public_method"));
  }

Verspotten Sie die private Methode der Unterklasse

Verwenden Sie PowerMockito.when (). Verwenden Sie außerdem "MemberMatcher.method ()", um eine private Methode anzugeben.

  @Test
public void Kann private Methoden von Unterklassen verspotten() throws Exception {
    PowerMockito.when(testSubClass, MemberMatcher.method(TestSubClass.class, "sub_private_method"))
        .withNoArguments().thenReturn("mocked_sub_private_method");

    assertThat(instance.public_subclass_private_method(), is(
        "public_subclass_method called subclass_public_method called mocked_sub_private_method"));
  }

Verspotten Sie das öffentliche Feld einer Unterklasse

Verwenden Sie "Whitebox.setInternalState ()", um ein Modell für ein Unterklassenfeld festzulegen.

  @Test
public void Kann öffentliche Felder von Unterklassen verspotten() {
    Whitebox.setInternalState(testSubClass, "public_field", "mocked_public_field");
    assertThat(instance.public_subclass_public_method(),
        is("public_subclass_method called subclass_public_method has mocked_public_field"));
  }

Verspotten Sie die privaten Felder der Unterklasse

Verwenden Sie "Whitebox.setInternalState ()", um ein Modell für ein Unterklassenfeld festzulegen. Entspricht der Einstellung im öffentlichen Bereich.

  @Test
public void Kann private Felder von Unterklassen verspotten() {
    Whitebox.setInternalState(testSubClass, "private_field", "mocked_private_field");
    assertThat(instance.public_subclass_private_method(), is(
        "public_subclass_method called subclass_public_method called subclass_private_method has mocked_private_field"));
  }

Es ist ein langer Satz, aber das war's.

Recommended Posts

Ordnungsgemäße Verwendung von Mockito und PowerMock
Verwenden Sie redirect_to und rendern Sie richtig
Richtige Verwendung der Schnittstelle und der abstrakten Klasse
Kriterien für die ordnungsgemäße Verwendung von render und redirect_to
[Java8] Angemessene Verwendung von Compareable und Comparator unter dem Gesichtspunkt der Mitarbeitersortierung
(In 1 Minute bestimmen) Wie verwende ich leer ?, Leer? Und präsent?
Verwenden Sie doch die for-Anweisung? Verwenden Sie die while-Anweisung? Ordnungsgemäße Verwendung von for-Anweisung und while-Anweisung
Verwendung der Datumsklasse
Mockito + PowerMock Spickzettel
Verwendung japanischer Schriftarten und Fremdzeichen in Jasper Report
Minimaler Einsatz von Mockito
Bis zur Verwendung von Spring Data und JPA Part 2
Bis zur Verwendung von Spring Data und JPA Part 1
Verwendung von Abstract Class und Interface in Java richtig
Umgang mit Datum und Uhrzeit in Ruby. Verwenden Sie Datum und Uhrzeit richtig.
Hintergrund und Mechanismus des Stoffladers
Zusammenfassung von FileInputStream und BufferedInputStream
Kombination von Suche und jedem_mit_Index
Urteil von JSONArray und JSONObject
Verspotten und spionieren Sie PowerMock aus
Verwenden Sie @ValueSource von ParametrisedTest von JUnit5
Rest- und Leistungstreiber (冪 Leistung)
Vor- und Nachteile von Java
[Docker-compose] Verwendung unbenannter und benannter Volumes von Volumes. Binden Sie die Halterung