Vraag Hoe test ik een privéfunctie of een klas met privémethoden, velden of innerlijke klassen?


Hoe deel ik een test (met behulp van xUnit) een klasse met interne privémethoden, velden of geneste klassen? Of een functie die privé is gemaakt door te hebben interne koppeling (static in C / C ++) of bevindt zich in een privé (anoniem) naamruimte?

Het lijkt niet de moeite waard om de toegangsmodificator voor een methode of functie te wijzigen om een ​​test te kunnen uitvoeren.


2265


oorsprong


antwoorden:


Als je een beetje een erfenis hebt Java toepassing, en het is niet toegestaan ​​om de zichtbaarheid van uw methoden te wijzigen, de beste manier om privémethoden te testen is om te gebruiken reflectie.

Intern gebruiken we helpers om te krijgen / in te stellen private en private static variabelen evenals aanroepen private en private static methoden. Met de volgende patronen kunt u vrijwel alles doen met betrekking tot de privémethoden en -velden. Natuurlijk kun je niet veranderen private static final variabelen door reflectie.

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

En voor velden:

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Opmerkingen:
  1. targetClass.getDeclaredMethod(methodName, argClasses) laat je kijken private methoden. Hetzelfde geldt voor    getDeclaredField.
  2. Het setAccessible(true) is vereist om met privépartijen te spelen.


1416



De beste manier om een ​​privémethode te testen, is via een andere openbare methode. Als dit niet kan worden gedaan, dan is een van de volgende voorwaarden waar:

  1. De privémethode is de dode code
  2. Er is een ontwerpgeur in de buurt van de klasse die u aan het testen bent
  3. De methode die u probeert uit te proberen, moet niet privé zijn

506



Als ik privémethodes in een klas heb die voldoende gecompliceerd zijn, voel ik de behoefte om de privémethoden direct te testen, dat is een codegeur: mijn klas is te gecompliceerd.

Mijn gebruikelijke aanpak om dergelijke problemen aan te pakken, is om een ​​nieuwe klasse te vinden die de interessante stukjes bevat. Vaak kunnen deze methode en de velden waarmee het samenwerkt en misschien een andere methode of twee in een nieuwe klasse worden geëxtraheerd.

De nieuwe klasse stelt deze methoden bloot aan 'publiek', zodat ze toegankelijk zijn voor unit-testen. De nieuwe en oude klassen zijn nu beide eenvoudiger dan de originele klas, wat geweldig is voor mij (ik moet dingen simpel houden, of ik verdwaal!).

Merk op dat ik niet suggereer dat mensen klassen creëren zonder hun hersenen te gebruiken! Het gaat er hier om de krachten van unit testing te gebruiken om u te helpen goede nieuwe klassen te vinden.


271



ik heb gebruikt reflectie om dit in het verleden voor Java te doen, en naar mijn mening was het een grote fout.

Strikt genomen zou je dat moeten doen niet schrijf eenheidstests die directe methoden testen. Wat jij moeten testen is het openbare contract dat de klas heeft met andere objecten; je moet de binnenkant van een voorwerp nooit rechtstreeks testen. Als een andere ontwikkelaar een kleine interne verandering in de klas wil aanbrengen, wat geen invloed heeft op het openbare contract van de klas, moet hij / zij uw op reflectie gebaseerde test aanpassen om ervoor te zorgen dat deze werkt. Als je dit in een project herhaaldelijk doet, stoppen unit-tests dan met een nuttige meting van de code-status en worden ze een belemmering voor ontwikkeling en een ergernis voor het ontwikkelingsteam.

Wat ik in plaats daarvan aanbeveel, is het gebruik van een code coverage tool zoals Cobertura, om ervoor te zorgen dat de unit tests die je schrijft zorgen voor een fatsoenlijke dekking van de code in privé-methoden. Op die manier test je indirect wat de privémethoden aan het doen zijn en handhaaf je een hogere mate van behendigheid.


229



Uit dit artikel: Privémethoden testen met JUnit en SuiteRunner (Bill Venners), je hebt eigenlijk 4 opties:

  • Test geen privémethoden.
  • Geef de toegang tot het methodepakket.
  • Gebruik een geneste testklasse.
  • Gebruik reflectie.

187



Over het algemeen is een unit-test bedoeld om de openbare interface van een klasse of eenheid uit te oefenen. Daarom zijn privémethoden implementatiedetails die u niet expliciet zou verwachten te testen.


96



Slechts twee voorbeelden van waar ik een privémethode zou willen testen:

  1. Decryptieroutines - Ik zou niet wil ze zichtbaar maken voor iedereen om alleen voor te zien in het belang van testen, anders kan iedereen dat gebruik ze om te decoderen. Maar zij zijn intrinsiek aan de code, gecompliceerd, en moet altijd werken (de voor de hand liggende uitzondering is reflectie die kan worden gebruikt om zelfs privémethoden te bekijken in de meeste gevallen, wanneer SecurityManager is niet geconfigureerd om dit te voorkomen).
  2. Een SDK maken voor gemeenschap consumptie. Hier neemt het publiek het op zich geheel andere betekenis, sinds dit is code die de hele wereld kan zien (niet alleen intern voor mijn applicatie). ik zet code in privé-methoden als ik dat niet doe wil dat de SDK-gebruikers het zien - I zie dit niet als code, ruik gewoon hoe SDK-programmering werkt. Maar van Natuurlijk moet ik mijn nog steeds testen particuliere methoden, en ze zijn waar de functionaliteit van mijn SDK eigenlijk woont.

Ik begrijp het idee om alleen het "contract" te testen. Maar ik zie niet dat iemand kan pleiten om geen code te testen - je kilometers kunnen variëren.

Dus mijn afweging betreft het compliceren van de JUnits met reflectie, in plaats van het in gevaar brengen van mijn beveiliging en SDK.


56



De private methoden worden aangeroepen door een openbare methode, dus de invoer van uw openbare methoden moet ook de private methoden testen die worden opgeroepen door die openbare methoden. Wanneer een openbare methode mislukt, kan dat een fout zijn in de privémethode.


53