ja, det här är miljon dollarfrågan. Hur enhet testa privata metoder?
ska en utvecklare testa de privata metoderna i sin kodbas? eller att lämna dem på förtroende för offentliga metoder är ett sätt. Varje utvecklare har sin egen åsikt att om vi faktiskt ska testa dem eller inte. Så, i ett nötskal, frågan blev reducerad till är ” finns det något bra tillvägagångssätt vi kan försöka för det här jobbet?”
Så här är alla möjliga alternativ tillgängliga för en utvecklare för att testa privata metoder för sina Java / kotlin-baserade appar 2019:
- testa inte privata metoder bisexuell (inga rötter, inga sura druvor)
- ge metoderna allmänhetens tillgång till bisexuell (Nej, Jag kommer inte att göra det det är emot kodningspraxis. Jag är en bra utvecklare, Jag följer best practices)
- använd en kapslad testklass bisexuell (det här är inte bra för blandad produktionskod med testkod. Behöver jag nämna igen att jag är en bra utvecklare och jag följer bara bästa praxis)
- använd Java Reflection Bisexual(Ja, det verkar intressant Jag är med på det)
trots den gemensamma tron är det faktiskt möjligt att komma åt privata fält och metoder för andra klasser via Java Reflection. Det är inte ens så svårt. Detta kan vara mycket praktiskt under enhetstestning.
Obs: Detta fungerar bara när du kör koden som en fristående Java-applikation, som du gör med enhetstester och vanliga applikationer. Om du försöker göra detta i en Java-Applet måste du fikla runt med SecurityManager. Men eftersom det inte är något du behöver göra så ofta, är det hittills utelämnat från denna text.
metod Parameter reflektion stöd lades till i Java 8. Enkelt uttryckt ger det stöd för att få namnen på parametrar vid körning.
för att komma åt ett privat fält måste du ringa metoden Class.getDeclaredField(String name)
eller Class.getDeclaredFields()
. MetodernaClass.getField(String name)
ochClass.getFields()
metoder returnerar bara offentliga fält, så de fungerar inte. Här är ett enkelt exempel på en klass med ett privat fält, och under det koden för att komma åt det fältet via Java-reflektion:
public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}
}PrivateObject privateObject = new PrivateObject("The Private Value");Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");privateStringField.setAccessible(true);String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
detta kodexempel kommer att skriva ut texten "fieldValue = The Private Value”
, vilket är värdet på det privata fältet privateString
I PrivateObject
instansen som skapades i början av kodexemplet.
Lägg märke till användningen av metoden PrivateObject.class.getDeclaredField("privateString")
. Det är detta metodsamtal som returnerar det privata fältet. Den här metoden returnerar bara fält som deklarerats i den aktuella klassen, inte fält som deklarerats i några superklasser.
Lägg märke till raden i fetstil också. Genom att anropaField.setAcessible(true)
stänger du av åtkomstkontrollerna för just dennaField
instans, endast för reflektion. Nu kan du komma åt det även om det är privat, skyddat eller paketomfång, även om den som ringer inte ingår i dessa omfattningar. Du kan fortfarande inte komma åt fältet med den normala koden. Kompilatorn tillåter det inte.
åtkomst till privata metoder
för att komma åt en privat metod måste du ringa metoden Class.getDeclaredMethod(String name, Class parameterTypes)
eller Class.getDeclaredMethods()
. MetodernaClass.getMethod(String name, Class parameterTypes)
ochClass.getMethods()
metoder returnerar bara offentliga metoder, så de fungerar inte.
Här är ett enkelt exempel på en klass med en privat metod, och under det koden för att komma åt den metoden via Java-reflektion:
public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {
this.privateString = privateString;
}private String getPrivateString(){
return this.privateString;
}
}PrivateObject privateObject = new PrivateObject("The Private Value");Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);privateStringMethod.setAccessible(true);String returnValue = (String)
privateStringMethod.invoke(privateObject, null);System.out.println("returnValue = " + returnValue);
detta kodexempel kommer att skriva ut texten "returnValue = The Private Value”
, vilket är det värde som returneras med metoden getPrivateString()
när den anropas på PrivateObject
den instans som skapades i början av den ursprungliga versionen kodexempel.
Lägg märke till användningen av metoden PrivateObject.class.getDeclaredMethod("privateString")
. Det är detta metodsamtal som returnerar den privata metoden. Denna metod returnerar endast metoder som deklarerats i den specifika klassen, inte metoder som deklarerats i några superklasser.
Lägg märke till raden i fetstil också. Genom att anropaMethod.setAcessible(true)
stänger du av åtkomstkontrollerna för just dennaMethod
instans, endast för reflektion. Nu kan du komma åt det även om det är privat, skyddat eller paketomfång, även om den som ringer inte ingår i dessa omfattningar. Du kan fortfarande inte komma åt metoden med den normala koden. Kompilatorn tillåter det inte.
Låt oss prova denna kunskap till någon produktionsnivå kod.
här är klassen som innehåller några privata metoder som vi vill testa.