2009-10-20 8 views
1

Je conçois souvent le système où j'ai une classe dans mon système qui a un tas de méthodes protégées. Les méthodes protégées sont cela parce qu'elles devraient être accessibles aux spécialisations, et en tant que telles, je considère que les méthodes protégées sont un contrat entre ma classe générale et n'importe quelles classes spécialisées.Quel est le nom du motif?

donc je veux vérifier que ces méthodes se comportent correctement, donc mes tests unitaires auront besoin d'accéder aux méthodes protégées, ce qui est impossible dans C#, sauf en utilisant hacks sales comme réflexion.

La solution que je choisis normalement est que je crée une classe spécialisée dans mon test unitaire qui expose ces méthodes protégées comme publiques. Étant donné que je garde toujours les tests unitaires dans un ensemble distinct, le code système lui-même n'a pas accès à ces classes et, à l'intérieur de mon code système, la fonction protégée reste protégée.

// In the system code assembly 
namespace MySystem { 
    public class SomeClass { 
     protected void DoSomething() { 
      ... 
     } 
    } 
} 

// In the unit test assembly 
namespace MySystem.Unittests { 
    public class SomeClass2 : SomeClass { 
     public new void DoSomething() { 
      base.DoSomething(); 
     } 
    } 
} 

Mon test unitaire est maintenant en mesure de tester le comportement du membre protégé sur la classe parente par instancier la classe spécialisée. J'utilise aussi ceci encore plus loin pour pouvoir mocker les appels d'objet et de fonction fictive aux fonctions virtuelles protégées, mais ce code est un peu plus complexe, donc je vais juste le découper.

Je trouve cette façon d'accomplir cette tâche si simple que je ne peux pas être la seule personne à le faire, et donc je suppose qu'il doit y avoir une convention de nommage commune pour cela?

+0

J'utilise simplement des interfaces et laisse les méthodes privées seules lors des tests. Ils ne devraient pas être beaucoup de toute façon si vous suivez le SRP. –

+0

Je renommer SomeClass2 à TestableSomeClass. Cela clarifie le pourquoi et quoi. (Et, oui, nous utilisons beaucoup ce modèle ici ...) –

+0

@Arjan - bien un point de ma question était de savoir quoi appeler SomClass2;) – Pete

Répondre

1

Je l'ai fait seulement quand je ne contrôle pas la classe nécessaire pour être testé. Charles indique ce que vous pouvez faire dans .NET lorsque vous contrôlez le code source. Votre cas est un peu différent en ce sens que votre classe est destinée à être utilisée en tant que superclasse, donc le tester via une sous-classe a beaucoup de sens (puisque la classe n'est pas destinée à être autonome). Dans ce cas, vous faites essentiellement une variante de Test-Specific Subclass. Le modèle décrit dans le lien est plus sur le comportement de dépassement, et est très utile si vous avez une classe qui n'a pas été écrite premier test et a un couplage élevé, c'est un bon moyen de séparer la dépendance (généralement comme une étape intermédiaire obtenir une classe séparée passée en paramètre). Dans votre cas, le "overriding" est dans le but d'augmenter l'accès, mais il semble correspondre au même modèle.

+0

En fait, après avoir lu la description du modèle, je dirais que La sous-classe spécifique au test est exactement ce que je fais. Le modèle décrit la «sous-classe exposant le comportement» comme un exemple de sous-classe spécifique au test. Je n'étais pas au courant de ce site, mais il semble génial, et je pense que là-bas je trouverai l'inspiration pour construire un meilleur code de test, merci pour ça! (J'ai déjà commandé le livre) – Pete

1

Je ne sais pas d'un nom de modèle pour whaty que vous faites, mais .net a une solution pour cette ... Faites les méthodes protégées interne, puis ajouter ce qui suit aux projets AssemblyInfo fichier

[assembly: InternalsVisibleToAttribute("[FQN of TestAssembly]")] 

Cela rendra les méthodes internes du projet visibles à l'ensemble de test spécifié dans l'attribut

2

Je ne suis pas sûr de voir le point, en général, pour tester vos méthodes protégées, cependant, je parle de un point de vue TDD. Généralement, vos tests sont écrits par rapport aux méthodes publiques de la classe. Des méthodes protégées apparaissent lorsque vous refactorisez du code pour extraire des méthodes courantes utilisées en interne. Comme ceux-ci proviennent de refactorings, vos tests existants couvrent déjà le code en cours de refactoring. Les tests ultérieurs pour le code qui utilise les méthodes refacturées via les méthodes publiques de spécialisations testent également le code - dans ce cas, les méthodes publiques de la spécialisation fonctionnent correctement lors de l'utilisation des méthodes communes protégées.

Dans les rares cas où un test explicite d'une méthode protégée a un sens, je ne vois pas le mal à utiliser la réflexion pour effectuer le test. Vous rompez seulement l'encapsulation pour le but du test après tout.

Questions connexes