9

Ho una libreria di classi che desidero eseguire il test dell'unità utilizzando il framework di test dell'unità Microsofts. Alcune delle classi che voglio testare sono configurate usando le impostazioni dell'applicazione. Queste impostazioni sono definite all'interno del file Settings.settings con ambito applicazione e valori predefiniti adatti. Quando la libreria viene utilizzata dall'applicazione, queste impostazioni possono essere sostituite nel file App.Config. In caso contrario, vengono utilizzati i valori predefiniti. È esattamente come voglio che sia.Modifica delle impostazioni dell'applicazione nei test di unità

In alcuni dei miei casi di test voglio testare combinazioni speciali di valori di impostazione ma non so come modificare i valori visti dalla classe sotto test dal codice di test dell'unità. Queste impostazioni avranno sempre il loro valore predefinito caricato dagli attributi della classe generata dal codice.

Nella mia classe biblioteca ho accedere alle impostazioni in questo modo:

var mySetting1 = Settings.Default.MySetting1; 
var mySetting2 = Settings.Default.MySetting2; 

Come faccio a modificare queste impostazioni in un test di unità prima della impostazione si accede dalla classe in prova? Rendere la classe delle impostazioni interne accessibile dal test dell'unità non risolve il problema poiché le impostazioni hanno scope di applicazione e sono proprietà di sola lettura nella classe delle impostazioni.

risposta

14

Dopo speleologia nelle classi ApplicationSettingsBase e associati mi è venuta in mente questa soluzione al mio problema. Non particolarmente bello, ma sicuramente ha il compito.

La classe delle impostazioni generate dal codice è interna al progetto della libreria di classi e deve essere accessibile al progetto di test dell'unità. Aggiungere l'attributo [assembly: InternalsVisibleTo("UnitTestAssemblyName")] a AssemblyInfo.cs nel progetto di libreria di classi.

Le impostazioni vengono caricate in modo pigro dagli attributi nella classe delle impostazioni quando si accede a un valore. Il primo passo è fare una lettura "fittizia" di un'impostazione per forzare questo carico pigro. Quando si esegue il test delle unità, si desidera evitare che i valori delle impostazioni modificati in un test influiscano su un altro, quindi è necessario "ripristinare" le impostazioni prima di caricarle lentamente. Questo può essere fatto usando il metodo Reload(). Questo codice viene inserito nel metodo di prova di inizializzazione: esistono ora

Settings.Default.Reload(); 
var dummy = Settings.Default.MySetting1; 

I valori di riferimento e possono essere impostati in ogni metodo di prova. Ricordatevi di utilizzare il tipo corretto come i getter codice generato farà un cast:

Settings.Default.PropertyValues["MyStringSetting1"].PropertyValue = "Foobar"; 
Settings.Default.PropertyValues["MyDoubleSetting2"].PropertyValue = 3.1416D; 
+0

+1 per la soluzione alternativa di Ricarica + Proprietà. –

+0

Grazie per questo, non l'avrei mai capito da solo. –

5

Vorrei creare una classe wrapper attorno alla classe Settings quindi passare quell'involucro. Quindi puoi deridere la tua classe di impostazioni con facilità.

L'unica altra cosa che mi viene in mente è l'opzione un po 'più leggera e più facile da prendere in giro per fare in modo che il file delle impostazioni implementa un'interfaccia che rifletta tutte le impostazioni. Non è molto diverso per il chiamante, ma avrai meno risorse idrauliche da fare quando aggiungi nuove impostazioni.

Né è fantastico, ed è un dolore doverlo fare per il codice generato automaticamente, ma sembra che sia quello con cui siamo bloccati per quanto posso dire se vuoi davvero rimuovere la dipendenza dal file delle impostazioni.

E.g. per un file di impostazioni che contiene un ambiente stringa di Applicazione e un ambiente int Utente:

internal sealed partial class Settings : IMySettings { 

    /* 
    * here be auto-generate code (and dragons!) 
    */ 
} 

internal interface IMySettings 
{ 
    string ApplicationSetting 
    { 
     get; 
    } 

    string UserSetting 
    { 
     get; 
     set; 
    } 
} 
+0

avrei preferito evitare l'iniezione di impostazioni dal momento che ho molte biblioteche e il numero di dipendenze per iniettare cresce molto come mi muovo nella gerarchia delle dipendenze .Inoltre, le classi di wrapping generate da Visual Studio sono noiose. Speravo in una soluzione che non fosse pura DI, ma funzionasse bene con le impostazioni delle applicazioni in .NET. –

+0

Purtroppo non penso che ce ne sia uno, il meglio che si possa fare è impostare l'impostazione dell'utente, ma le impostazioni dell'applicazione non cambieranno al di fuori del file. L'unica altra cosa che riesco a immaginare al momento è l'utilizzo di un'interfaccia, leggermente più leggera ma ancora, come dici tu, pura DI. –