Domanda

Mettiamo tutti i nostri test unitari nei loro progetti. Scopriamo che dobbiamo rendere pubbliche alcune classi anziché interne solo per i test unitari. C'è comunque modo di evitare di doverlo fare. Quali sono le implicazioni della memoria rendendo pubbliche le classi anziché sigillate?

È stato utile?

Soluzione

Se si utilizza .NET, InternalsVisibleTo l'attributo assembly ti consente di creare " amico " assiemi. Si tratta di assemblee specifiche con un forte nome che possono accedere alle classi interne e ai membri dell'altra assemblea.

Nota, questo dovrebbe essere usato con discrezione in quanto accoppia strettamente gli assiemi coinvolti. Un uso comune per InternalsVisibleTo è per i progetti di unit testing. Probabilmente non è una buona scelta per l'uso negli assiemi di applicazioni reali, per il motivo sopra indicato.

Esempio:

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

Altri suggerimenti

Se si tratta di una classe interna, non deve essere utilizzata isolatamente. Pertanto non dovresti davvero provarlo a parte testare qualche altra classe che utilizza quell'oggetto internamente.

Proprio come non dovresti testare membri privati ??di una classe, non dovresti testare classi interne di una DLL. Tali classi sono dettagli di implementazione di alcune classi accessibili al pubblico e pertanto dovrebbero essere ben esercitate attraverso altri test unitari.

L'idea è che si desidera testare solo il comportamento di una classe perché se si verificano i dettagli dell'implementazione interna, i test saranno fragili. Dovresti essere in grado di modificare i dettagli di implementazione di qualsiasi classe senza interrompere tutti i tuoi test.

Se scopri che hai davvero bisogno di testare quella classe, allora potresti voler riesaminare perché quella classe è interna in primo luogo.

a scopo di documentazione

in alternativa puoi creare un'istanza della classe interna usando il metodo Type.GetType

Esempio

//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*/ });

per il tipo generico ci sono diversi processi come qui sotto:

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*/});

Le classi possono essere sia pubbliche che sigillate.

Ma non farlo.

Puoi creare uno strumento per riflettere sulle classi interne ed emettere una nuova classe che accede a tutto tramite la riflessione. MSTest lo fa.

Modifica: voglio dire, se non si desidera includere roba di prova di alcun tipo nell'assieme originale; questo funziona anche se i membri sono privati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top