2014-10-04 17 views
5

Ho classe A che sto testando un metodo su quell'unità che prende la classe B come parametro. La classe B è ciò che sto cercando di prendere in giro, ed è una classe astratta. La classe è simile al di sotto.Come si prende in giro una classe astratta contenente un metodo astratto interno usando Moq?

public abstract class B 
{ 
    internal abstract void DoSomething(); 
} 

Il mio test di unità è simile.

[TestMethod] 
public void ClassA_Add_TestSomething() 
{ 
    var classA = new A(); 
    var mock = new Mock<B>(); 

    classA.Add(mock.Object); 

    // Assertion 
} 

Ricevo la seguente eccezione.

Metodo TestSomething ha gettato un'eccezione:
System.ArgumentException: Tipo di deridere deve essere un'interfaccia o una classe astratta o non sigillati. ---> System.TypeLoadException: Metodo 'DoSomething' nel tipo 'Castle.Proxies.BProxy' dall'assembly 'DynamicProxyGenAssembly2, Version = 0.0.0.0, Culture = neutral, PublicKeyToken = null' non ha un'implementazione.

Posso aggirare questo rendendo il metodo virtuale anziché astratto, ma non è quello che voglio realizzare con il design dell'API. Ho anche provato a fornire un'implementazione attraverso mock.Setup(m => m.DoSomething()) senza alcun risultato. Questo è possibile con Moq, o dovrò creare una classe di test concreta che deriva dalla classe B astratta? Volevo evitare di creare tipi concreti, che tipo di sconfitte hanno lo scopo di usare una struttura di derisione o di stoppaggio, o sono fuorviato qui?

Modifica Ho scoperto che se faccio il metodo public abstract questo problema non si verifica. Quindi immagino che la vera domanda sia se questo è possibile anche con un metodo interno quando si utilizza InternalsVisibleTo e Moq.

+0

Perché non puoi usare mock.Setup? – brz

+0

Ricevo l'eccezione se utilizzo l'installazione o meno. Nel mio test unitario, non mi importa se 'B.DoSomething' ha o no un'implementazione, anche se capisco perché ne avrebbe bisogno.È possibile che io non stia usando 'Setup' correttamente, ma ciò che ho provato era piuttosto semplice' mock.Setup (m => m.DoSomething()). Callback (() => {}); ' –

+4

Considerare attentamente perché hai un metodo 'internal abstract' su una classe pubblica. Altri non saranno in grado di implementare il metodo astratto perché non è visibile a loro. Forse questo è quello che vuoi, anche se poi consiglierei di rendere anche i costruttori interni così nessuno ha l'idea di poter implementare la classe astratta. –

risposta

3

Considerare attentamente perché si ha un metodo internal abstract in una classe pubblica. Altri non saranno in grado di implementare il metodo astratto perché non è visibile a loro. Forse questo è quello che vuoi. A volte, dati vari vincoli di progettazione, questo è un approccio valido. Se la tua libreria sarà consumata da altri, consiglierei almeno di rendere anche i costruttori interni così che nessuno possa avere l'idea di implementare la classe astratta.

5

Moq si affida a Castle Dynamic Proxy per implementare i suoi mock. In fase di runtime, un nuovo assembly viene creato e caricato nell'AppDomain tramite Moq (il nome DynamicProxyGenAssembly2 visualizzato nel messaggio di eccezione).

Il problema è che questa assemblea non può accedere alle classi interne e dei membri del proprio codice, perché non sono visibili all'esterno del montaggio dove li hai dichiarato.

Un soluzione è quello di marcare l'assembly con il InternalsVisibleToAttribute e specificare il nome del gruppo generato dinamicamente:

[InternalsVisibleTo("DynamicProxyGenAssembly2")] 

Ricordate però che questa soluzione si basa su un dettaglio di implementazione, e potrebbe smettere di funzionare in futuro versioni.

+2

Questo è utile in generale, ma nel mio caso InternalsVisibleTo è già applicato in modo appropriato. Il problema è con Moq che gestisce il metodo interno su un tipo astratto, in particolare. La risposta alla fine fu come suggeriva MikeZ, che era di ripensare il design. –

+1

Come menzionato @ DavidAnderson-DCOM, questa soluzione non funziona in questo caso. Posso confermare questo nei miei test. –

Problemi correlati