Domanda

Quando state testando un'unità un'applicazione che si basa sui valori di un file app.config? Come si verifica che questi valori vengano letti correttamente e come il programma reagisce a valori errati immessi in un file di configurazione?

Sarebbe ridicolo dover modificare il file di configurazione per l'app NUnit, ma non riesco a leggere i valori dall'app.config che voglio testare.

Modifica: penso che dovrei chiarire forse. Non sono preoccupato che ConfigurationManager non riesca a leggere i valori, ma mi occupo di testare come il mio programma reagisce ai valori letti.

È stato utile?

Soluzione

Solitamente isola le dipendenze esterne come leggere un file di configurazione nella propria classe di facciata con funzionalità molto ridotte. Nei test posso creare una versione simulata di questa classe che implementa e usa quella invece del vero file di configurazione. Puoi creare i tuoi mockup o utilizzare un framework come moq o rhino mock per questo.

In questo modo puoi facilmente provare il tuo codice con diversi valori di configurazione senza scrivere test complessi che prima scrivono file di configurazione xml. Il codice che legge la configurazione è in genere così semplice che richiede pochissimi test.

Altri suggerimenti

È possibile modificare la sezione di configurazione in fase di esecuzione nella configurazione del test. Per esempio:

// setup
System.Configuration.Configuration config = 
     ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.Sections.Add("sectionname", new ConfigSectionType());
ConfigSectionType section = (ConfigSectionType)config.GetSection("sectionname");
section.SomeProperty = "value_you_want_to_test_with";
config.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("sectionname");

// carry out test ...

Puoi ovviamente impostare i tuoi metodi di supporto per farlo in modo più elegante.

Puoi chiamare il metodo set di ConfigurationManager.AppSettings per impostare i valori richiesti per quel particolare test unitario.

[SetUp]
public void SetUp()
{
  ConfigurationManager.AppSettings.Set("SettingKey" , "SettingValue");
  // rest of unit test code follows
}

Quando viene eseguito il test unitario, utilizzerà questi valori per eseguire il codice

Puoi sia leggere che scrivere nel file app.config con la classe ConfigurationManager

Ho riscontrato problemi simili con web.config .... Trovo una soluzione interessante. È possibile incapsulare la funzione di lettura della configurazione, ad es. qualcosa del genere:

public class MyClass {

public static Func<string, string> 
     GetConfigValue = s => ConfigurationManager.AppSettings[s];

//...

}

E quindi normalmente utilizza

string connectionString = MyClass.GetConfigValue("myConfigValue");

ma nel test unitario inizializzare "sovrascrivi" la funzione in questo modo:

MyClass.GetConfigValue = s =>  s == "myConfigValue" ? "Hi", "string.Empty";

Ulteriori informazioni:

http: // rogeralsing. com / 2009/05/07 / il-più semplice forma-di-configurabile-dipendenza-iniezione /

Una soluzione più elegante consiste nell'utilizzare una semplice iniezione di dipendenza vecchia sulle impostazioni di configurazione stesse. IMHO è più pulito del dover deridere una classe di lettura / wrapper di configurazione ecc.

Ad esempio, dì una classe " Meteo " richiede un " ServiceUrl " per funzionare (ad esempio dire che chiama un servizio web per ottenere il tempo). Piuttosto che avere una riga di codice che attivamente va a un file di configurazione per ottenere quell'impostazione (sia che quel codice sia nella classe Weather o un lettore di configurazione separato che potrebbe essere deriso secondo alcune delle altre risposte), la classe Weather può consentire l'impostazione da iniettare, tramite un parametro al costruttore, o eventualmente tramite un setter di proprietà. In questo modo, i test unitari sono estremamente semplici e diretti e non richiedono nemmeno beffe.

Il valore dell'impostazione può quindi essere iniettato utilizzando un contenitore Inversion of Control (o Dependency Injection), quindi gli utenti della classe Weather non devono fornire esplicitamente il valore da qualche parte, poiché viene gestito dal contenitore.

Ha funzionato per me:

 public static void BasicSetup()
  {
     ConnectionStringSettings connectionStringSettings = 
          new ConnectionStringSettings();
     connectionStringSettings.Name = "testmasterconnection";
     connectionStringSettings.ConnectionString = 
          "server=localhost;user=some;database=some;port=3306;";
     ConfigurationManager.ConnectionStrings.Clear();
     ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);
  }

Puoi sempre racchiudere il bit di lettura in un'interfaccia e far leggere un'implementazione specifica dal file di configurazione. Dovresti quindi scrivere test usando Mock Objects per vedere come il programma ha gestito valori errati. Personalmente, non testerei questa specifica implementazione, in quanto si tratta del codice .NET Framework (e presumo - si spera - che lo abbia già testato la MS).

System.Configuration.Abstractions è una cosa bella quando si tratta di testare questo tipo di cose.

Ecco il sito del progetto GitHub con alcuni buoni esempi: inserisci qui la descrizione del link

Ecco il sito NuGet: https://www.nuget.org/packages /System.Configuration.Abstractions/

Lo uso in quasi tutti i miei progetti .NET.

In realtà, riflettendoci ulteriormente, suppongo che cosa dovrei fare è creare una classe ConfigFileReader da utilizzare nel mio progetto e quindi falsificarla nel cablaggio dell'unità di test?

È la solita cosa da fare?

L'opzione più semplice è racchiudere i metodi che leggono la configurazione in modo da poter sostituire i valori durante il test. Creare un'interfaccia che si utilizza per leggere la configurazione e fare in modo che un'implementazione di tale interfaccia venga passata come parametro del costruttore o impostata sull'oggetto come proprietà (come si farebbe con l'iniezione di dipendenza / inversione del controllo). Nell'ambiente di produzione, passare un'implementazione che legge davvero dalla configurazione; nell'ambiente di test, passare un'implementazione di test che restituisce un valore noto.

Se non hai la possibilità di refactoring del codice per verificabilità ma hai ancora bisogno di testarlo, Typemock Isolator offre la possibilità di deridere effettivamente le classi di configurazione di .NET framework in modo da poter dire " la prossima volta che chiederò tale-e-tale appSettings valore, restituisce questo valore noto. "

Ho avuto lo stesso problema,

è possibile utilizzare Nunit-console.exe c: \ path1 \ testdll1.dll c: \ path2 \ testdll2.dll

funziona bene anche se entrambe le DLL puntano a differenti app.configs ex testdll1.dll.config e testdll2.dll.config

se si desidera utilizzare la configurazione del progetto Nunit e racchiudere queste due dll, non è possibile avere due configurazioni

devi avere project1.config se il tuo progetto Nunit è project1.nunit nella stessa posizione in cui si trova Project1.nunit.

spero che questo aiuti

Beh, ho appena avuto lo stesso problema ... Volevo testare un progetto BL a cui fa riferimento un sito web. ma volevo testare solo il BL. Quindi nell'evento pre-build del progetto di test copio i file app.Config nella cartella bin \ debug e li faccio riferimento da app.config ...

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