Rendre le code interne mais disponible pour les tests unitaires à partir d'autres projets

StackOverflow https://stackoverflow.com/questions/106907

  •  01-07-2019
  •  | 
  •  

Question

Nous avons mis tous nos tests unitaires dans leurs propres projets. Nous constatons que nous devons rendre certaines classes publiques au lieu d’internes uniquement pour les tests unitaires. Y a-t-il un moyen d'éviter de faire cela? Quelles sont les implications pour la mémoire en rendant les classes publiques au lieu d’être scellées?

Était-ce utile?

La solution

Si vous utilisez .NET, le InternalsVisibleTo L'attribut d'assemblage vous permet de créer un " ami " assemblées. Ce sont des assemblys spécifiques fortement nommés qui sont autorisés à accéder aux classes internes et aux membres de l'autre assemblage.

Notez que ceci doit être utilisé avec discrétion car il couple étroitement les assemblées impliquées. InternalsVisibleTo est couramment utilisé pour les projets de tests unitaires. Ce n'est probablement pas un bon choix pour une utilisation dans vos assemblages d'applications réels, pour la raison indiquée ci-dessus.

Exemple:

[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{

Autres conseils

S'il s'agit d'une classe interne, elle ne doit pas être utilisée seule. Par conséquent, vous ne devriez pas vraiment le tester à part tester une autre classe qui utilise cet objet en interne.

Tout comme vous ne devriez pas tester les membres privés d'une classe, vous ne devriez pas tester les classes internes d'une DLL. Ces classes sont des détails d’implémentation de certaines classes accessibles au public et doivent donc être bien exercées au moyen d’autres tests unitaires.

L'idée est que vous voulez uniquement tester le comportement d'une classe, car si vous testez les détails de l'implémentation interne, vos tests seront alors fragiles. Vous devriez pouvoir modifier les détails d’implémentation de toute classe sans interrompre tous vos tests.

Si vous estimez que vous devez réellement tester cette classe, vous voudrez peut-être réexaminer la raison pour laquelle cette classe est interne.

à des fins de documentation

Vous pouvez également instancier une classe interne à l'aide de la méthode Type.GetType

.

exemple

//IServiceWrapper is public class which is 
//the same assembly with the internal class 
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
    .CreateInstance(type, new object[1] { /*constructor parameter*/ });

pour le type générique, le processus ci-dessous est différent:

var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
     .CreateInstance(genType, new object[1] { /*constructor parameter*/});

Les classes peuvent être publiques ET scellées.

Mais ne faites pas ça.

Vous pouvez créer un outil de réflexion sur les classes internes et émettre une nouvelle classe qui accède à tout via la réflexion. MSTest fait cela.

Éditer: Je veux dire, si vous ne voulez pas inclure de matériel de test dans votre assemblage original; cela fonctionne aussi si les membres sont privés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top