0 votes

Test d'une méthode utilisée à partir d'une classe abstraite

Je dois tester une méthode (runMethod()) qui utilise une méthode d'une classe abstraite inhérente pour créer un booléen. La méthode de la classe abstraite utilise des documents Xml et des nœuds pour récupérer des informations. Le code ressemble un peu à ceci (et c'est extrêmement simplifié, mais c'est l'énoncé de mon problème)

namespace AbstractTestExample
{
public abstract class AbstractExample
{
    public string propertyValues;
    protected XmlNode propertyValuesXML;
    protected string getProperty(string propertyName)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(new System.IO.StringReader(propertyValues));
        propertyValuesXML= doc.FirstChild;

        XmlNode node = propertyValuesXML.SelectSingleNode(String.Format("property[name='{0}']/value", propertyName));
        return node.InnerText;
    }
}

public class AbstractInheret : AbstractExample
{
    public void runMethod()
    {
        bool addIfContains = (getProperty("AddIfContains") == null || getProperty("AddIfContains") == "True");
        //Do something with boolean
    }
}
}

Le code veut donc obtenir une propriété d'un document Xml créé et l'utilise pour transformer le résultat en un booléen. Ma question est la suivante : quelle est la meilleure solution pour m'assurer que j'ai le contrôle sur le comportement du résultat booléen ? J'utilise Moq pour un éventuel mocking.

Je sais que cet exemple de code est probablement un peu flou, mais c'est le meilleur que j'ai pu montrer. J'espère que vous pourrez m'aider.

EDIT : Ce dont j'ai besoin, en fait, c'est.. :
J'ai besoin de pouvoir contrôler getProperty() pendant que je teste la classe AbstractInheret.

1voto

JJoos Points 355

Puisque la valeur du booléen est contrôlée par le xml, vous pourriez refactoriser votre code, de sorte que vous puissiez facilement définir le xml.

Comme ceci :

namespace AbstractTestExample
{
    public abstract class AbstractExample
    {
        protected XmlNode propertyValuesXML;

        protected string getProperty(string propertyName)
        {
            XmlNode node = propertyValuesXML.FirstChild.SelectSingleNode(String.Format("property[name='{0}']/value", propertyName));
            return node.InnerText;
        }
    }

    public class AbstractInheret : AbstractExample
    {
        public AbstractInheret(string propertyValues){

            propertyValuesXML = new XmlDocument();
            propertyValuesXML.Load(new System.IO.StringReader(propertyValues));
        }

        public void runMethod()
        {
            bool addIfContains = (getProperty("AddIfContains") == null || getProperty("AddIfContains") == "True");
            //Do something with boolean
        }
    }
}

De cette façon, vous n'avez pas besoin de simuler quoi que ce soit et vous pouvez facilement passer une chaîne de xml à votre classe. Vous devriez également vérifier les conditions d'erreur impliquant un xml non valide passé au constructeur.

0voto

Jim Hurne Points 2584

Si je comprends bien votre question, vous voulez savoir comment contrôler le résultat de getProperty afin de pouvoir tester addIfContains avec différentes valeurs booléennes.

Si vous avez des difficultés à écrire un test pour quelque chose, cela signifie souvent que vous essayez de tester trop de choses, ou qu'il y a un problème dans la conception du code.

Vous pourriez rendre ce code plus testable en évitant d'utiliser l'héritage. Comme vous l'avez découvert, l'héritage est souvent difficile à gérer dans les tests unitaires (il y a beaucoup de couplage étroit), et la délégation fonctionne généralement mieux de toute façon. Je recommanderais d'apporter la modification suivante à la conception :

namespace TestExample
{
    public interface PropertyManager {
      public string getProperty(string propertyName);
    }

    public class XmlPropertyManager: PropertyManager {
      public string getProperty(string propertyName) {
      //...xml parsing code here
      }
    }

    public class Example {
      private PropertyManager propertyManager;

      public void runMethod() {
        bool addIfContains = (propertyManager.getProperty("AddIfContains") == null || propertyManager.getProperty("AddIfContains") == "True");
        //Do something with boolean
      }
    }
}

Vous pouvez alors facilement simuler le PropertyManager.

Si votre conception exige que vous utilisiez une classe de base abstraite (pour d'autres fonctions que getProperty), vous pouvez toujours utiliser l'approche par délégation :

namespace TestExample
{
    public interface PropertyManager {
      public string getProperty(string propertyName);
    }

    public class XmlPropertyManager: PropertyManager {
      public string getProperty(string propertyName) {
      //...xml parsing code here
      }
    }

    public abstract class AbstractExample
    {
       protected PropertyManager propertyManager;

       //... other important methods
    }

    public class AbstractInheret: AbstractExample {

      public void runMethod() {
        bool addIfContains = (propertyManager.getProperty("AddIfContains") == null || propertyManager.getProperty("AddIfContains") == "True");
        //Do something with boolean
      }
    }
}

0voto

Nayan Points 1817

Je ne sais pas exactement ce que vous voulez dire par cette question.

"Quelle est la meilleure solution pour s'assurer que j'ai le contrôle sur le comportement des résultats booléens ?

Je suppose que vous avez besoin de la valeur booléenne d'une propriété. Cela pourrait donc faire l'affaire !

    public static bool GetBoolean(string boolStr)
    {
        bool bVal = default(bool);
        try
        {
            bVal = Convert.ToBoolean(boolStr);
        }
        catch (Exception) {
            bVal = default(bool);
        }
        return bVal;
    }

Il suffit de l'insérer dans le code et tout devrait bien se passer :)

0voto

Jim Hurne Points 2584

Si, pour une raison quelconque, vous ne pouvez pas remanier votre code de la manière décrite dans ma première réponse (par exemple, si un tiers fournit la classe de base abstraite), vous pouvez créer une sous-classe de AbstractInherit qui surcharge uniquement la méthode getProperty. Notez que je n'aime pas vraiment ce type d'approche, car elle couple vos tests à l'implémentation interne de la classe. Mais parfois, vous n'avez pas le choix.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X