être - using methods c#




Unité testant des méthodes privées en C# (6)

"Il n'y a rien appelé standard ou meilleure pratique, ce ne sont probablement que des opinions populaires".

C'est la même chose pour cette discussion.

Tout dépend de ce que vous pensez être une unité, si vous pensez que UNIT est une classe, alors vous ne frapperez que la méthode publique. Si vous pensez que UNIT est une ligne de code qui frappe des méthodes privées, vous ne vous sentirez pas coupable.

Si vous souhaitez appeler des méthodes privées, vous pouvez utiliser la classe "PrivateObject" et appeler la méthode invoke. Vous pouvez regarder cette vidéo YouTube ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) qui montre comment utiliser "PrivateObject" et discute si les tests de méthodes privées sont logiques ou non.

Visual Studio permet le test unitaire de méthodes privées via une classe d'accesseur générée automatiquement. J'ai écrit un test d'une méthode privée qui compile avec succès, mais échoue à l'exécution. Une version assez minimale du code et du test est:

//in project MyProj
class TypeA
{
    private List<TypeB> myList = new List<TypeB>();

    private class TypeB
    {
        public TypeB()
        {
        }
    }

    public TypeA()
    {
    }

    private void MyFunc()
    {
        //processing of myList that changes state of instance
    }
}    

//in project TestMyProj           
public void MyFuncTest()
{
    TypeA_Accessor target = new TypeA_Accessor();
    //following line is the one that throws exception
    target.myList.Add(new TypeA_Accessor.TypeB());
    target.MyFunc();

    //check changed state of target
}

L'erreur d'exécution est:

Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.

Selon intellisense - et donc je suppose que la compilateur - cible est de type TypeA_Accessor. Mais à l'exécution, il est de type TypeA, et donc l'ajout de la liste échoue.

Est-il possible que je puisse arrêter cette erreur? Ou, peut-être plus probablement, quel autre conseil les autres ont-ils (je prédis peut-être «ne pas tester les méthodes privées» et «ne pas avoir de tests unitaires manipuler l'état des objets»).


Dans VS 2005/2008, vous pouvez utiliser un accesseur privé pour tester un membre privé, mais cette façon de procéder a été supprimée dans la version ultérieure de VS.


Une autre idée ici est d'étendre les tests aux classes / méthodes "internes", donnant plus de sens à ces tests. Vous pouvez utiliser InternalsVisibleToAttribute sur l'assembly pour les exposer à des modules de test unitaires distincts.


Une façon de tester les méthodes privées est la réflexion. Cela vaut aussi pour NUnit et XUnit:

MyObject objUnderTest = new MyObject();
MethodInfo methodInfo = typeof(MyObject).GetMethod("SomePrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
object[] parameters = {"parameters here"};
methodInfo.Invoke(objUnderTest, parameters);

Vous pouvez utiliser la classe PrivateObject

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(retVal, expectedVal);

TL; DR: Extrait une méthode privée à une autre classe, test sur cette classe; En savoir plus sur le principe SRP (principe de responsabilité unique)

Il semble que vous avez besoin d'extraire la méthode private à une autre classe; dans ce devrait être public . Au lieu d'essayer de tester sur la méthode private , vous devez tester public méthode public de cette autre classe.

Nous avons le scénario suivant:

Class A
+ outputFile: Stream
- _someLogic(arg1, arg2) 

Nous devons tester la logique de _someLogic ; mais il semble que la Class A prenne plus de rôle qu'elle n'en a besoin (violer le principe du SRP); juste refactoriser en deux classes

Class A1
    + A1(logicHandler: A2) # take A2 for handle logic
    + outputFile: Stream
Class A2
    + someLogic(arg1, arg2) 

De cette façon, someLogic pourrait être testé sur A2; dans A1 il suffit de créer un faux A2 puis d'injecter au constructeur pour tester que A2 est appelé à la fonction someLogic .





unit-testing