Java >> Java tutorial >  >> Tag >> private

Unit Test Private Methods i Java

1. Oversigt

I denne artikel vil vi kort forklare, hvorfor det generelt ikke er en god idé at teste private metoder direkte. Derefter vil vi demonstrere, hvordan man tester private metoder i Java, hvis det er nødvendigt.

2. Hvorfor vi ikke bør teste private metoder

Som regel bør de enhedstest, vi skriver, kun kontrollere vores offentlige metodekontrakter. Private metoder er implementeringsdetaljer, som opkalderne af vores offentlige metoder ikke er opmærksomme på. Desuden bør ændring af vores implementeringsdetaljer ikke føre til, at vi ændrer vores tests.

Generelt fremhæver opfordring til at teste en privat metode et af følgende problemer:

  • Vi har død kode i vores private metode.
  • Vores private metode er for kompleks og burde tilhøre en anden klasse.
  • Vores metode var ikke beregnet til at være privat i første omgang.

Derfor, når vi føler, at vi har brug for at teste en privat metode, er det, vi virkelig bør gøre, at løse det underliggende designproblem i stedet for.

3. Et eksempel:Fjern død kode fra en privat metode

Lad os vise et hurtigt eksempel på det.

Vi vil skrive en privat metode, der returnerer det dobbelte af et heltal . For null værdier, vil vi returnere null :

private static Integer doubleInteger(Integer input) {
    if (input == null) {
        return null;
    }
    return 2 * input;
}

Lad os nu skrive vores offentlige metode. Det vil være det eneste indgangssted uden for klassen.

Denne metode modtager et heltal som input. Det bekræfter, at dette heltal er ikke nul , ellers kaster den en IllegalArgumentException . Derefter kalder den den private metode for at returnere to gange heltal 's værdi:

public static Integer validateAndDouble(Integer input) {
    if (input == null) {
        throw new IllegalArgumentException("input should not be null");
    }
    return doubleInteger(input);
}

Lad os følge vores gode praksis og teste vores offentlige metodekontrakt.

Lad os først skrive en test, der sikrer, at en IllegalArgumentException kastes, hvis input er null :

@Test
void givenNull_WhenValidateAndDouble_ThenThrows() {
    assertThrows(IllegalArgumentException.class, () -> validateAndDouble(null));
}

Lad os nu tjekke, at et heltal ikke er nul er korrekt fordoblet:

@Test
void givenANonNullInteger_WhenValidateAndDouble_ThenDoublesIt() {
    assertEquals(4, validateAndDouble(2));
}

Lad os se på dækningen rapporteret af JaCoCo plugin:

Som vi kan se, er nul-tjekket i vores private metode ikke dækket af vores enhedstest. Skal vi så teste det?

Svaret er nej! Det er vigtigt at forstå, at vores private metode ikke eksisterer i et vakuum. Det vil først blive kaldt, efter at data er valideret i vores offentlige metode. Således vil nul-tjekket i vores private metode aldrig nås:Det er død kode og bør fjernes.

4. Sådan testes private metoder i Java

Hvis vi antager, at vi ikke afskrækkes fra at teste vores private metode, så lad os forklare, hvordan vi kan gøre det konkret.

For at teste det ville det være nyttigt, hvis vores private metode havde en anden synlighed . Den gode nyhed er, at vi vil være i stand til at simulere det med refleksion .

Vores indkapslingsklasse hedder Utils . Ideen er at få adgang til den private metode kaldet doubleInteger som accepterer et heltal som en parameter. Derefter vil vi ændre dens synlighed, så den er tilgængelig uden for Utils klasse. Lad os se, hvordan vi kan gøre det:

private Method getDoubleIntegerMethod() throws NoSuchMethodException {
    Method method = Utils.class.getDeclaredMethod("doubleInteger", Integer.class);
    method.setAccessible(true);
    return method;
}

Nu er vi i stand til at bruge denne metode. Lad os skrive en test, der vil kontrollere det givet et nul objekt, returnerer vores private metode null . Vi bliver nødt til at anvende metoden på en parameter, der vil være null :

@Test
void givenNull_WhenDoubleInteger_ThenNull() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
    assertEquals(null, getDoubleIntegerMethod().invoke(null, new Integer[] { null }));
}

Lad os kommentere lidt mere om brugen af ​​invoke metode. Det første argument er det objekt, som vi anvender metoden på. Som doubleInteger er statisk, bestod vi i en nul . Det andet argument er en række parametre. I dette tilfælde havde vi kun én parameter, og den var null .

Til sidst, lad os demonstrere, hvordan vi også kunne teste tilfældet af et ikke-null input:

@Test
void givenANonNullInteger_WhenDoubleInteger_ThenDoubleIt() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    assertEquals(74, getDoubleIntegerMethod().invoke(null, 37));
}

5. Konklusion

I denne artikel har vi beskrevet, hvorfor det generelt ikke er en god idé at teste private metoder. Derefter viste vi, hvordan man bruger refleksion til at teste en privat metode i Java.

Som altid er koden tilgængelig på GitHub.


Java tag