JUnit 4 PermGen taille de débordement lors de l'exécution des tests dans Eclipse et Maven2
Je suis en train de faire quelques tests unitaires avec JUnit, PowerMock et Mockito. J'ai beaucoup de test de classes annotées avec @RunWith(PowerMockRunner.class)
et @PrepareForTest(SomeClassesNames)
pour se moquer de finale classes et plus de 200 cas de test.
Récemment, j'ai couru dans un problème de PermGen space débordement quand je lance mon test complet de la suite dans Eclipse ou Maven2. Quand je lance mon test un par un, puis chacun d'eux réussit.
J'ai fait quelques recherches à ce sujet, cependant, aucun de ces conseils m'ont aidé (j'ai augmenté PermGenSize et MaxPermSize). Récemment, j'ai découvert qu'il y est une classe qui ne contient que des méthodes statiques et chaque méthode renvoie un objet est moqué avec PowerMockito. Je me demande si c'est une bonne pratique, et c'est peut-être l'origine du problème, car les variables statiques sont partagés entre les tests unitaires?
D'une manière générale est-ce une bonne pratique d'avoir une classe statique avec beaucoup de méthodes statiques qui renvoie statique est moqué d'objets?
Je suppose que de ce que l'OP a dit que les méthodes statiques sont utilisés dans les tests, ils n'retour moqué des objets. Ils ne sont pas utilisés dans le non-code d'essai.
OK, je l'ai lu différemment. @Adam, pouvez-vous préciser? Sont les méthodes statiques partie de votre application, ou tout simplement tester un échafaudage?
Afin de clarifier les méthodes statiques sont une partie de test de l'échafaudage.
Pourquoi? Ne pouvez-vous pas juste de les rendre non-méthodes statiques quelle que soit la classe de test où ils vivent?
OriginalL'auteur BlueLettuce16 | 2012-07-27
Vous devez vous connecter pour publier un commentaire.
@Brice dit, les problèmes avec la PermGen seront à venir à partir de votre utilisation extensive de la moqué des objets. Powermock et Mockito à la fois de créer une nouvelle classe qui se trouve entre la classe se moquaient et votre code de test. Cette classe est créée au moment de l'exécution et chargés dans le PermGen, et est (pratiquement) jamais été retrouvé. Donc votre problème avec la PermGen space.
À votre question:
1) le Partage de variables statiques est considéré comme une odeur de code. Il est nécessaire, dans certains cas, mais il introduit depdendencies entre les tests. Test Un doit s'exécuter avant le test B.
2) l'Utilisation de méthodes statiques pour retourner un moqué de l'objet n'est pas vraiment une odeur de code, c'est un attern qui est souvent utilisé. Si vraiment vous ne pouvez pas augmenter votre permgen space, vous avez un certain nombre d'options:
Utiliser un pool d'objets fantaisie, avec
PowerMock#reset()
lorsque la maquette est mis de nouveau dans la piscine. Cela permettrait de réduire le nombre de créations que vous faites.Deuxièmement, vous avez dit que vos cours sont finales. Si c'est modifiable, vous pouvez simplement utiliser une classe anonyme dans le test. Ce nouveau coupe vers le bas sur la quantité de permgen space utilisé:
Troisièmement, vous pouvez introduire une interface (utilisation de Refactor->Extrait de l'Interface dans Eclipse), ce qui permet ensuite s'étendre à une classe vide qui ne fait rien. Puis, dans votre classe, vous faites comme ci-dessus. J'utilise cette technique beaucoup, parce que je trouve ça plus facile à lire:
alors dans la classe:
Je dois admettre que je ne suis pas particulièrement fan de se moquer, je ne l'utilise que lorsque cela est nécessaire, j'ai tendance à prolonger la classe avec une classe anonyme ou créer une véritable MockXXX classe. Pour plus d'informations sur ce point de vue, voir Se moquant des Moqueries et des Résultats de ces Tests. par Oncle Bob
Par la façon dont, dans maven infaillible, vous pouvez toujours forkMode=toujours qui va de la fourche de la jvm pour chaque classe de test. Cela ne résout pas votre problème d'Eclipse.
essayez @PowerMockIgnore(valeur = {"org.apache.log4j.*"}) gitshah.com/2010/07/how-to-fix-outofmemoryerror-when.html
bien répondu.. et merci pour le lien post de l'Oncle Bob 🙂
OriginalL'auteur Matthew Farwell
Je suis PermGen erreurs de Junit dans Eclipse. Mais je ne suis pas à l'aide de toutes les moqueries libs comme Mockito, ni EasyMock. Cependant, mon code de base est grande et mon Junit tests à l'aide de Printemps-Test (et sont intenses et complexes de cas de test). Pour cela, j'ai besoin de vraiment augmenter la PermGen pour l'ensemble de mes tests Junit.
Eclipse s'applique Installé le JRE paramètres de la Junit va pas l'éclipse.paramètres ini. Donc pour modifier ces:
Ce paramètre permettra Junit tests à exécuter, le plus intense de cas de tests dans Eclipse, et d'éviter les OutOfMemoryError: PermGen. Cela devrait également être à faible risque, car plus simple Junit tests ne seront pas allouer la totalité de la mémoire.
OriginalL'auteur Jay Meyer
Première : Mockito est à l'aide de CGLIB pour créer des objets fantaisie, et PowerMock est à l'aide de Javassist pour quelques autres trucs, comme le retrait de la finale de marqueurs, Powermock charge également des classes dans un nouveau chargeur de classe. CGLIB est connu pour manger de la Génération Permanente (juste google CGLIB PermGen pour trouver des résultats pertinents sur le sujet).
Ce n'est pas un droit de réponse car cela dépend des détails de votre projet :
Comme vous l'avez souligné, il est statique de la classe d'aide, je ne sais pas si détient les variables statiques et se moque ainsi, je ne connais pas les détails de votre code, donc c'est de la pure supposition, et les autres lecteurs qui sait vraiment mieux pourrait me corriger.
Il pourrait être le chargeur de classe (et au moins certains de ses enfants) que chargé de cette classe statique peut être gardé en vie à travers des tests - il pourrait être à cause de la statique (qui vit dans le Classe royaume) ou en raison d'une référence quelque part - ce qui signifie que si le chargeur de classe vit encore (c'est à dire ne sont pas des déchets collectés) ses classes chargées, ne sont pas défaussées c'est à dire les classes, y compris le générés sont encore dans le PermGen.
Ces classes peuvent également être énorme en taille, si vous avez beaucoup de ces classes soient chargées cela pourrait être pertinent d'avoir plus de PermGen valeurs, surtout depuis Powermock besoin pour recharger les classes dans un nouveau chargeur de classe pour chacun des tests.
Encore une fois je ne connais pas les détails de votre projet, donc je suis juste deviner, mais votre génération permanente problème peut être provoqué soit par le point 1 ou le point 2, ou même les deux.
De toute façon de manière générale, je dirais que oui : le fait d'avoir une classe statique qui pourrait revenir statique se moquaient de l'objet ne ressemble à une mauvaise pratique ici, comme c'est généralement dans le code de production. S'il est mal conçu, il peut conduit à des chargeurs de classes de fuite (c'est méchant!).
Dans la pratique, je l'ai vu courir des centaines de tests (avec Mockito seulement) sans modification des paramètres de mémoire et sans voir le CGLIB procurations en cours de déchargement, et je ne suis pas en utilisant statique des trucs appart celles de la Mockito API.
Si vous êtes à l'aide de Sun/Oracle JVM vous pouvez essayer ces options pour suivre ce qui se passe :
-XX:+TraceClassLoading
et-XX:+TraceClassUnloading
ou-verbose:class
Espère que ça aide.
En dehors de la portée de cette question :
Personnellement, je n'aime pas utiliser d'utiliser Powermock de toute façon, je ne l'utilise que dans des cas limites par exemple pour les tests inmodifiable du code legacy. Powermock est trop intrusif à mon humble avis, c'est de reproduire pour chaque test d'un nouveau chargeur de classe pour effectuer ses actes (modification du bytecode), vous avez fortement annoter les classes de test pour être en mesure de s'en moquer, ...
À mon avis, pour habitude de développement de tous ces petits désagréments emporte sur l'avantage de la capacité à se moquer de finale. Même Johan l'auteur de Powermock, une fois m'a dit qu'il était recommanding Mockito la place et de garder Powermock pour un but précis.
Ne vous méprenez pas: Powermock est un fantastique morceau de la technologie, qui a vraiment aider quand vous avez à traiter avec la (mal) conçu le code de legs que vous ne pouvez pas modifier. Mais pas pour tous les jours developpement, surtout si entraînée TDD.
oui c'est géant, j'ai une unité pure de la suite de tests de ~250 classes de test avec ~1220 méthodes d'essai qui utilise de manière intensive Mockito, et la génération permanente de la taille tops autour de 12 MO. Je n'ai vu une centaine(s) MO de PerMGen dans l'exécution des applications. Il pourrait prendre un certain temps, mais vous devriez vraiment essayer d'identifier ce qui est à l'origine de manger jusqu'à la PermGen. Peut-être que les tests ne sont pas vraiment des tests unitaires, et sont à l'aide de Printemps contextes, etc., cela pourrait être une explication légitime.
Le problème est que quand j'écris des cas de test pour une classe qui utilise mockito ou powermock (par exemple un gérant de classe), alors la classe qui est raillé est également chargé. Ce qui cause le problème est que chaque fois que cette classe est moqué il est chargé. J'ai découvert lorsque j'ai couru mes essais avec les paramètres que vous avez recommandé et -XX:+PrintGCDetails. Je l'initialisation se moque de la méthode annotée avec l'Alésage et de la méthode annotée avec l'Après-je attribuer à chacun d'eux la valeur null. Je ne sais pas pourquoi ces classes ne sont pas des ordures collectées. Je vais essayer d'appeler la collecte des ordures directement.
La collecte des ordures de l'Exécution.getRuntime().gc() n'aide pas 🙁 d'autres idées?
Ouais, c'est une question de cette CGLIB, si ces classes ne sont pas des ordures collectées, c'est certainement parce que le chargeur de classe est toujours référencé quelque part, peut-être par le biais de certains autres de la classe référencée dans un champ statique, ou quelque chose. De toute façon si c'est en effet un chargeur de classe de fuite, c'est le méchant, et il sera difficile de localiser et de résoudre. Vous pouvez aussi suivre les classes qui sont chargés plusieurs fois. Et il pourrait être intéressant de mesurer la mémoire pour chaque classe de test. De plus, vous pourriez avoir besoin de réellement analyser la mémoire avec des outils tels que jmap / Eclipse MAT / Netbeans profiler.
OriginalL'auteur Brice