6
votes

Méthode de test JUnit pour Getters & Setters

J'ai beaucoup de haricots Java dans mon projet. J'ai besoin de générer une classe de test Junit pour eux. Les méthodes de test générées à l'aide de Eclipse 3.2 & Junit 4.4 ressemblent aux éléments suivants: xxx

Certaines de mes haricots ont plus de 100 champs ...

y a-t-il un moyen de que je peux obtenir une seule méthode de test pour les getters & Setters tels que testemployee () , testName () de sorte que dans ces méthodes, je peux tester à la fois mes configurateurs et getters plutôt que d'utiliser 2 diff. Méthodes de test pour eux ...

Comment dois-je configurer Eclipse pour faire cela?


3 commentaires

Quel plug-in Eclipse utilisez-vous pour générer les méthodes de test?


FWIW, la question suivante tente de mettre de côté le débat et de demander s'il existe un moyen de le faire automatiquement par votre préférence - Stackoverflow.com/questions/ 108692


Le problème réel est totalement sans rapport avec les tests unitaires tout à fait: " Certains de mes haricots ont plus de 100 champs " ... pour tous les débutants Java lisant cette question, s'il vous plaît Comprenez ceci est la programmation terrible . Toute classe qui a plus de 100 champs a trop de responsabilités. Voir Ce si vous ne comprenez pas pourquoi.


5 Réponses :


24
votes

La philosophie du développement axé sur les tests dit "Testez tout ce qui peut éventuellement casser". C'est-à-dire concentrer vos efforts sur les tests utiles, au lieu d'écrire des tests pour le fait de celui-ci.

Getters et Setters sont presque toujours du code trivial, ce qui ne vaut pas la peine d'être testé par eux-mêmes.

Je sais que ce n'est pas une réponse directe à votre plaidoyer, mais je pensais qu'il pourrait toujours aider à le pointer de la sortie ;-) Alors pourquoi avez-vous réellement besoin d'écrire des tests pour tous ces getters et setters en premier lieu? < / p>


12 commentaires

+1 Je conviens que les méthodes accessores n'ont pas besoin de test. Il me manque une fonctionnalité qui leur permettrait d'être déclarée par une annotation.


Je ne suis pas d'accord fortement. Vous testez les ensembles et les getters pour régression , de sorte que lorsque vos sets / getters changent plus complexes, les tests confirment qu'ils fonctionnent toujours comme avant.


Oui, serait bien. Java est trop verbeux à des occasions. C # obtenu celui-ci mieux.


Checkout ProjectLombok.org "Lombok pour une approche basée sur l'annotation, ou passez à quelque chose comme groovy. Groovy est une sorte de Java ++, mais ajoute également une programmation dynamique. Vous n'avez pas à l'utiliser, mais c'est là. Peut renommer un .java à .groovy et Groovyc est heureux. Ensuite, peut utiliser des fonctionnalités voulant de là.


@Brian: IMO Votre cas est entièrement couvert par la maxime ci-dessus. S'il y a une chance assez forte que ma mise en œuvre de getter / setter puisse devenir plus complexe dans un avenir prévisible, j'écris mes petits tests bien sûr. Cependant, je dirais que votre "quand" ressemble toujours à un assez grand "si" à moi ;-)


Je suis d'accord avec @brian. Oui, il est vrai que la plupart des getters et des setters sont triviaux, ce qui les teste trivial. Cependant, mis à part le point d'essai de régression que @brian a fait, les tester peut également s'assurer que les choses se déroulent correctement par des constructeurs. Ou si quelqu'un étend votre classe et ne doit pas quelque chose correctement. J'ai fait valoir cela avec d'autres périodes de piment, mais elles sont toujours extrêmement faciles à mettre en œuvre, plus facile que de discuter à ce sujet parfois, surtout sur les chances hors probabilité que cela vous préparait plus tard.


@Casey: Si vous êtes convaincu que vous êtes convaincu que les tests d'une unité d'écriture pour Getters & Setters sont le meilleur investissement de vos compétences et de vos tests d'unité, prenez-y :-) moi-même, travailler avec le code hérité (pour la plupart de ma carrière ... comme c'est Je crois), je dois admettre que, habituellement, ces tests sont généralement sur ma liste de tests d'unités pour écrire. Si seulement c'étaient mes plus gros inquiétudes ...


@ PÉTER Bien dans mon expérience (courte que cela puisse être), lorsque vous travaillez avec le code hérité, c'est un jeu d'autre balle entier. J'ai travaillé avec un site asp.net/c# au cours des 6 derniers mois maintenant, essayant d'adapter le test de l'unité sans causer trop de dégâts. Toute la chose est horriblement écrite et j'ai concentré mes tests de l'unité sur certaines parties qui ont vraiment besoin de rester travailler et refactoriser quoi et quand je peux le contourner.


@Case sonne bien - juste les langues et acronymes varient :-) :-(


@ PÉTER YEAH. C'est presque toujours les mêmes concepts, juste une syntaxe différente.


Tester les getters and Setters dévaleut votre couverture de code et que le getter et les setters devraient être utilisés par certains comportements testés ailleurs (leur donnant ainsi la couverture) ou ils doivent être supprimés car ils ne sont pas testés dans le cadre d'un comportement (et donc devraient donc ne pas être utilisé dans le code de production). La dévaluation provient de ne pas pouvoir trouver de code non utilisé par aucun comportement et qui inclut des getters et des setters inutilisés.


@Steven Il dévalue la métrique de couverture de code, mais lorsque la direction vous dicte, vous avez besoin de 90% de couverture de code, vous devez presque commencer à tester les getters et les setters. Je suis d'accord avec Peter ici, testez les choses qui comptent et ont du sens. Je comprends la théorie de tester les getters / setters Brian mentionne, mais comme Devs, nous n'avons pas tous un temps d'infini à dépenser pour tester, car la théorie dit que nous devrions. Avec le temps limité, je suis d'abord testé le code critique (code avec High CCM, classes avec haine ca). Tous les codes ne sont pas égaux.



5
votes

Vous pourriez peut-être utiliser les "beansutils" Apache Commons 'pour aider à l'automatiser:

http://commons.apache.org/beanutils/apidocs/org/apache/commons/beanutils/propertyutils.html#getsimpleSimpleProperty % 28java.lang.Object, java.lang.string% 29

Par exemple, il existe une méthode décrire (Object haricot) qui retournera une carte de tous les attributs lisibles (c.-à-d. getters).

puis itérer cette carte et cette carte: xxx

et xxx

Et bien que je suis d'accord avec l'autre affiche que les getters / setters sont assez triviaux - je pense que cela vaut toujours la peine de les tester - d'éliminer les fautes de frappe, de tester les auditeurs de changement de propriété, etc.

Par exemple, cette extraire de manière dynamique les getters d'un haricot: xxx

Vous devrez télécharger à la fois des beanutils et des biens de la communogue et des bocaux des deux bibliothèques à votre pro JECT pour exécuter ce code.


0 commentaires

11
votes

Si vous avez 100 champs dans une classe (avec des ensembles / getters correspondants), je suppose que votre modèle d'objet n'est pas décomposé correctement. 100+ champs sonnent comme un nombre extraordinaire de champs pour un objet, et je devinerais qu'il a plusieurs responsabilités pouvant être divisées sur plusieurs objets plus spécialisés.


1 commentaires

Bien que ce soit souvent le cas, il peut ne pas nécessairement avoir tort d'avoir ce nombre de champs. Imaginez que cette classe existe pour fournir une mappage JAXB dans un très grand fichier XML, par exemple.



3
votes

Je suppose que cette bibliothèque est la réponse à votre question: http://outidemybox.github.com/testutils/

Il teste toutes les valeurs initiales de la bean, les régleurs, les getters, le hashcode (), l'équivalent () et la totring (). Tout ce que vous avez à faire est de définir une carte de propriété / valeur non par défaut.

Il peut également tester des objets qui sont des haricots avec des constructeurs non par défaut supplémentaires.


1 commentaires

Juste pour référence future. Veuillez vous abstenir de copier et de coller des réponses et de la promotion automatique. Merci.



0
votes

Répondre à cela en 2021 parce que ce problème persiste toujours.

haricots s'ajoute à la base de code et avoir un impact très négatif si vos pipelines Devops imposent des restrictions de couverture sur les repos. Il y a deux façons de la surmonter. P>

  1. exclure les haricots (que je dirais ne devrait pas être fait). P> li>

  2. Écrivez les cas d'écriture pour les haricots (qui est la chose la plus pathétique que nous, en tant que développeur puisse faire pour perdre notre temps :(). P> li> ol>

    et dans la plupart des cas, vous finirez par écrir des étuis de test pour les haricots. P>

    J'ai écrit ce cas d'utilité / test simple qui utilise la réflexion et peut vous permettre d'augmenter le code Junit. Couverture et sauvegarder votre temps. P>

    Bean sous test: Ville P>

    package com.test.beans;
    
    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertNotNull;
    import static org.junit.jupiter.api.Assertions.fail;
    
    import java.beans.IntrospectionException;
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.junit.jupiter.api.Test;
    
    /**
     * @author ameena
     *
     */
    class BeanTest {
    
        public void invokeSetter(Object obj, String propertyName, Object variableValue)
        {
            PropertyDescriptor propDescriptor;
            try {
                propDescriptor = new PropertyDescriptor(propertyName, obj.getClass());
                Method setter = propDescriptor.getWriteMethod();
                try {
                    setter.invoke(obj,variableValue);
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    e.printStackTrace();
                    fail(e.getMessage());
                }
            } catch (IntrospectionException e) {
                e.printStackTrace();
                fail(e.getMessage());
            }
    
        }
    
        public Object invokeGetter(Object obj, String variableName)
        {
            Object returnValue = null;
            try {
                PropertyDescriptor pd = new PropertyDescriptor(variableName, obj.getClass());
                Method getter = pd.getReadMethod();
                returnValue = getter.invoke(obj);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) {
                e.printStackTrace();
                fail(e.getMessage());
            }
            return returnValue;
        }
    
    
        private <T extends Object> void validateGettersSetters(List<T> objects) {
            for (T t : objects) {
                Class<?> aClass = t.getClass();
                for (java.lang.reflect.Field field : aClass.getDeclaredFields()) {
                    System.out.println(field);
                    Class<?> c = field.getType();
                    if (c == String.class) {
                        invokeSetter(t, field.getName(), "dummy");
                        assertEquals("dummy", (invokeGetter(t, field.getName())));
                    } else if (c == Integer.class || c == int.class) {
                        invokeSetter(t, field.getName(), 1);
                        assertEquals(1, (invokeGetter(t, field.getName())));
                    }else if (c == Double.class || c == double.class) {
                        invokeSetter(t, field.getName(), 1d);
                        assertEquals(1d, (invokeGetter(t, field.getName())));
                    }else if (c == Long.class || c == long.class) {
                        invokeSetter(t, field.getName(), 1l);
                        assertEquals(1l, (invokeGetter(t, field.getName())));
                    }else if (c == Boolean.class || c == boolean.class) {
                        invokeSetter(t, field.getName(), true);
                        assertEquals(true, (invokeGetter(t, field.getName())));
                    }else if (c == List.class){
                        //Now based on your bean and filed name
                        switch(field.getName()) {
                        case "neighbourCities" :
                            invokeSetter(t, field.getName(), new ArrayList<City>());
                            assertNotNull(invokeGetter(t, field.getName()));
                            break;
                    }
                }
            }
        }
        }
    
        @Test
        void testBean() {
            List<Object> objects = new ArrayList<>();
            objects.add(new City());
            validateGettersSetters(objects);
    
        }
    
    }
    


0 commentaires