2011-10-01 15 views
5

Ho isolato i test NUnit per la mia app C# in un assembly chiamato Tests.dll. Il file di configurazione associato è chiamato Tests.dll.config. Questo è ciò che Nunit utilizza piuttosto che il vero file di configurazione della mia app. Sembra che questo (che mostra solo un paio di opzioni di configurazione ci sono molti altri):Manipolazione del file app.config per i test delle unità

<?xml version="1.0" encoding="utf-8"?> 

<configuration> 
    <appSettings> 
    <add key="useHostsFile" value="true" /> 
    <add key="importFile" value="true" /> 

    </appSettings> 
</configuration> 

Per garantire la mia app viene accuratamente testato, ho bisogno di modificare le opzioni di configurazione tra i test. Dopo aver eseguito un paio di test, vorrei aggiungere alcuni nuovi valori di configurazione al file e farli utilizzare dai test successivi. Quale codice dovrei aggiungere per farlo?

+0

Puoi spiegare meglio il caso d'uso? Perché dovresti cambiare test.dll.config in runtime? –

+1

Questa è esattamente la stessa domanda di questo: http://stackoverflow.com/questions/168931/unit-testing-the-app-config-file-with-nunit –

+0

OK, immagino possa essere chiuso. Grazie per il puntatore. – FunLovinCoder

risposta

3

Si consiglia di implementare un'interfaccia IConfig con proprietà useHostsFile e importFile. Quindi rimuoverò tutte le dipendenze dirette in questo file, tranne che nella classe ConfigDefault che implementa IConfig. In questa implementazione si carica il normale file di configurazione. Per ogni test è possibile implementare un'altra classe che eredita anche da IConfig. Suggerisco di usare una iniezione di dipendenza. Ninject è gratuito e facile da usare.

0

Io uso questo codice:

[TestMethod] 
    public void Test_general() 
    { 
     var cs = new ConnectionStringSettings(); 
     cs.Name = "ConnectionStrings.Oracle"; 
     cs.ConnectionString = "DATA SOURCE=xxx;PASSWORD=xxx;PERSIST SECURITY INFO=True;USER ID=xxx"; 
     cs.ProviderName = "Oracle.DataAccess.Client"; 

     var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
     //config.ConnectionStrings.ConnectionStrings.Clear(); 
     config.ConnectionStrings.ConnectionStrings.Remove(cs.Name); 
     config.ConnectionStrings.ConnectionStrings.Add(cs); 
     config.Save(ConfigurationSaveMode.Modified); 
     ConfigurationManager.RefreshSection("connectionStrings"); 

     // your code for your test here 
    } 
0

Ecco i miei due centesimi a questa sfida. Semplicemente, crea una nuova classe AppSettings come livello di astrazione. In normali operazioni leggerà semplicemente le impostazioni dal file di configurazione dell'applicazione. Ma i test unitari possono sovrascrivere le impostazioni su una base per thread, consentendo l'esecuzione di test unitari in parallelo con diverse impostazioni.

internal sealed class AppSettings 
{ 
    private static readonly AppSettings instance; 
    private static ConcurrentDictionary<int, AppSettings> threadInstances; 
    private string _setting1; 
    private string _setting2; 

    static AppSettings() { instance = new AppSettings(); } 

    internal AppSettings(string setting1 = null, string setting2 = null) { 
     _setting1 = setting1 != null ? setting1 : Properties.Settings.Default.Setting1; 
     _setting2 = setting2 != null ? setting2 : Properties.Settings.Default.Setting2; 
    } 

    internal static AppSettings Instance { 
     get { 
      if (threadInstances != null) { 
       AppSettings threadInstance; 
       if (threadedInstances.TryGetValue(Thread.CurrentThread.ManagedThreadId, out threadInstance)) { 
        return threadInstance; 
       } 
      } 
      return instance; 
     } 

     set { 
      if (threadInstances == null) { 
       lock (instance) { 
        if (threadInstances == null) { 
         int numProcs = Environment.ProcessorCount; 
         int concurrencyLevel = numProcs * 2; 
         threadInstances = new ConcurrentDictionary<int, AppSettings>(concurrencyLevel, 5); 
        } 
       } 
      } 

      if (value != null) { 
       threadInstances.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, value, (key, oldValue) => value); 
      } else { 
       AppSettings threadInstance; 
       threadInstances.TryRemove(Thread.CurrentThread.ManagedThreadId, out threadInstance); 
      } 
     } 
    } 

    internal static string Setting1 => Instance._setting1; 

    internal static string Setting2 => Instance._setting2; 
} 

Nel codice dell'applicazione, le impostazioni di accesso utilizzando le proprietà statiche:

function void MyApplicationMethod() { 
    string setting1 = AppSettings.Setting1; 
    string setting2 = AppSettings.Setting2; 
} 

In unit test, impostazioni opzionalmente sovrascrivere selezionati:

[TestClass] 
public class MyUnitTest 
{ 
    [TestCleanup] 
    public void CleanupTest() 
    { 
     // 
     // Clear any app settings that were applied for the current test runner thread. 
     // 
     AppSettings.Instance = null; 
    } 

    [TestMethod] 
    public void MyUnitMethod() 
    { 
     AppSettings.Instance = new AppSettings(setting1: "New settings value for current thread"); 
     // Your test code goes here 
    } 
} 

NOTA: Come tutti i metodi delle AppSettings le classi sono dichiarate come interne è necessario renderle visibili all'assembly test unit utilizzando l'attributo: [assembly: InternalsVisibleTo ("< nome assembly >, chiave pubblica = < chiave pubblica > ")]

Problemi correlati