Domanda

[ Naturalmente, la domanda non è limitata a uno specifico "amico". implementazione, sentiti libero di indicare i dettagli dell'implementazione se pertinente ]

Leggendo le domande senza risposta, mi sono imbattuto in InternalsVisibleTo attributo:

  

Specifica i tipi che sono   normalmente visibile solo all'interno di   l'assemblea corrente è visibile a   un'altra assemblea.

La Guida alla programmazione C # su MSDN ha una sezione Assembly di amici che descrive come utilizzare l'attributo per consentire l'uso di metodi e tipi di internal a un altro assembly.

Mi chiedo se sarebbe una buona idea usarlo per creare un "nascosto" interfaccia per la strumentazione di una libreria utilizzata dall'assemblea di collaudo dell'unità. Sembra aumentare notevolmente l'accoppiamento in entrambe le direzioni (codice di test nell'assemblaggio di produzione, conoscenza interna intima dell'assemblaggio di produzione nel codice di test), ma d'altra parte potrebbe aiutare a creare test a grana fine senza ingombrare l'interfaccia pubblica.

Qual è la tua esperienza con l'utilizzo delle dichiarazioni degli amici durante i test? Era il tuo proiettile d'argento o è iniziata la Marcia della morte?

È stato utile?

Soluzione

Ho fatto ampio uso di questa tecnica - significa che i miei test unitari possono testare aspetti della libreria di codici che non sono visibili ai normali consumatori.

Mentre l'utilizzo di [InternalsVisibleTo] aumenta l'accoppiamento, credo che l'aumento (minore) valga la pena.

I miei test unitari sono già strettamente accoppiati al codice testato - anche se provo a scrivere test che assicurino risultati specifici, non implementazioni specifiche, accedendo a cose non visibili ai consumatori normali, vincolo in qualche modo l'implementazione.

In senso contrario, l'accoppiamento è minimo: avere l'attributo [InternalsVisibleTo] sull'assemblaggio del codice e contrassegnare alcune cose come interne anziché privato (o interno protetto invece di protetto ).

(Nota che sto ignorando qui eventuali modifiche al design che sono provocate dall'uso di Unit Testing, che è un'altra discussione.)

L'attributo [InternalsVisibleTo] richiede un nome sicuro per i tuoi assembly. Se non lo stai già facendo, potresti trovare questo un po 'oneroso in quanto un assembly con un nome forte può dipendere solo da altri assembly con un nome forte, il che potrebbe finire con la necessità di modificare diversi assembly.

Ottenere l'attributo giusto può essere un po 'complicato, poiché deve includere la chiave pubblica dell'assembly di test. IDesign ha un utile strumento di assemblaggio degli amici che crea l'attributo negli appunti, pronto per incollare. Consigliato.

Altri suggerimenti

È l'unico uso che io abbia mai applicato personalmente a InternalsVisibleTo - ed è stato davvero molto utile.

Non vedo i test unitari come test in black box: sono già associati all'implementazione in una certa misura. Essere in grado di testare tipi e metodi interni consente una messa a fuoco molto più stretta (unità più piccole).

Penso che usare InternalsVisibleToAttribute per abilitare i test unitari sia perfettamente ragionevole. La mia "unità" in "test unitari" è una classe e include classi interne , quindi voglio provarle. Non voglio unit test private metodi , tuttavia.

Non penso che creare una speciale interfaccia privata solo per i test sia una buona idea. Uno dei valori del test unitario è che ti dà la possibilità di pensare all'interfaccia per la tua classe dal punto di vista di un consumatore di quella classe; fornire una backdoor toglie quel vantaggio.

La mia preferenza, tuttavia, è quella di mettere i miei test unitari nello stesso assieme del mio codice di produzione. Di solito non influisce sul mio cliente, ma semplifica le cose per me, quindi lo faccio. Quando lo faccio, la domanda InternalsVisibleTo scompare.

In effetti, Unit Testing è il solo per il quale sono stato in grado di utilizzare il InternalsVisibleToAttribute . Con questo puoi implementare gran parte dei tuoi metodi "privati" come interni invece di esporli al framework di unit test per test più invasivi di invarianti interni alla classe.

Ho avuto un grande successo con questa tecnica. Se non altro ti aiuta ad avvicinarti a questo mitico obiettivo di copertura del codice al 100% permettendoti di invocare metodi privati ??in situazioni altrimenti inaccessibili.

Penso che un altro caso d'uso legittimo si presenti quando hai usato assembly separati quando hai riunito il codice C ++ legacy con il codice C # più recente.

Abbiamo preso gli assembly C ++, li abbiamo convertiti in C ++ / CLI e quindi implementiamo il codice più recente in C #. Quando lo facciamo, useremmo ancora " interno " per le classi / i metodi in C # che non sono realmente pubblici, quindi renderli disponibili per il codice legacy come assembly amici.

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