Verwendung von web.config beim Testen einer asp .net-Anwendung

74

Ich beginne mit Unit-Tests. Ich habe eine Methode, die die web.config für eine Verbindungszeichenfolge verwendet.

Ich hatte gehofft, verwenden zu können

[DeploymentItem("web.config")]

Um die Webkonfigurationsdatei zu erhalten, bleiben mir immer noch Nullreferenzausnahmen (dafür würde ich meinen nächsten Test schreiben).

Wie verwende ich die Konfigurationsdatei, die in dem Projekt enthalten ist, das ich testen möchte?

Ich verwende das in VS 2008 enthaltene Testframework, wenn dies einen Unterschied macht.

Vielen Dank

ilivewithian
quelle
Fügen Sie Ihren Unit-Test-Code in dasselbe Projekt ein wie Ihren Anwendungscode?
Gerrie Schenck
+1, ich hatte heute die gleiche Frage. Leider kann ich die gesuchte Antwort immer noch nicht finden, da ich einen Link zur aktuellen web.config in meiner Web-App hinzufügen und diese Werte beim Schreiben des Codes verwenden wollte, andernfalls eine app.config hinzufügen Da meine Tests meine Web-App-Konfiguration nicht testen würden, ist dies ein Teil der Informationen, die ich testen möchte, während ich meine App entwickle. Es ist jedoch sinnvoll, Tests nicht mit Code zu mischen, aber das ist manchmal schwierig.
Eugenio Miró

Antworten:

108

Unit-Test-Projekte sollten eine eigene Konfigurationsdatei haben.

In einem Testprojekt können Sie Hinzufügen, Neues Element, Anwendungskonfigurationsdatei auswählen.

Diese Datei verhält sich genau wie eine web.config, jedoch für Ihre Komponententests.

Gerrie Schenck
quelle
2
Ich habe versucht, was Sie vorgeschlagen haben, und meinem Testprojekt eine neue Konfigurationsdatei hinzugefügt. Die Verbindungszeichenfolge ist vorhanden, aber wenn ich meine Tests ausführe, sehe ich immer null in der Zeile var sqlCon = new SqlConnection (ConfigurationManager.ConnectionStrings ["SqlServer"]. ConnectionString); Was könnte mir fehlen?
ilivewithian
1
FWIW, ich habe eine Antwort auf eine ähnliche Frage gepostet ( stackoverflow.com/a/47355610/183174)[here] . Das Wesentliche ist, dass VS die Konfigurationsdateien überschreiben kann, die beim Erstellen des Testprojekts kopiert werden.
LostNomad311
14

Sie können eine web.config oder app.config von jedem Ort aus mit laden OpenMappedExeConfiguration. Stellen Sie sicher, dass System.Configurationes zu den Referenzen Ihres Projekts hinzugefügt wird.

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap()
fileMap.ExeConfigFilename = @"c:\my-web-app-location\web.config"

Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
string connectionString = config.AppSettings.Settings["ConnectionString"].Value;

Hier ist die web.config, ziemlich Standard.

<?xml version="1.0"?>
<configuration>
  <configSections>
  </configSections>
  <appSettings>
    <add key="ConnectionString" value="Data Source=XXXX;Initial Catalog=XXX; Trusted_Connection=True;"/>
  </appSettings>
</configuration>

Update am 29.09.2017

Ich habe eine Klasse entwickelt, um das Lesen von AppSetitngs aus einer Datei zu erleichtern. Ich habe die Idee von Zp Bappi .

public interface IAppSettings
{
    string this[string key] { get; }
}

public class AppSettingsFromFile : IAppSettings
{
    readonly Configuration Config;

    public AppSettingsFromFile(string path)
    {
        var fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = path;
        Config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
    }

    public string this[string key]
    {
        get
        {
            return Config.AppSettings.Settings[key].Value;
        }
    }
}

Hier erfahren Sie, wie Sie die Klasse verwenden.

IAppSettings AppSettings = new AppSettingsFromFile(@"c:\my-web-app-location\web.confg");
string connectionString = AppSettings["ConnectionString"];
Tony
quelle
7

Kopieren Sie Ihre Datei web.config in den Ordner "/ bin" und benennen Sie sie in "AppName.dll.config" um.

Wobei "AppName" - der Name der resultierenden Assembly ist.

Ich habe diesen Hack oft benutzt.

Alex
quelle
Bei mir hat es nicht funktioniert. Unit Test kennt ConnectionString in der Konfigurationsdatei nicht automatisch. Ich muss einen benutzerdefinierten Code schreiben, um ihn aus der Konfiguration zu lesen.
Orad
2
Das Hinzufügen einer einfachen app.config wie in der akzeptierten Antwort sollte in den meisten Fällen funktionieren. Dies ist ein Hack für einige seltsame Konfigurationen (wie "Ad-hoc-Test" in TestDriven)
Alex
Es funktionierte für mich mit der folgenden Einstellung in der .proj-Datei des Testprojekts: <ItemGroup> <None Include = ".. \ MyProject \ Web.config"> <Link> $ (TargetFileName) .config </ Link> <CopyToOutputDirectory> PreserveNewest </ CopyToOutputDirectory> </ Noone> </ ItemGroup> Danke
orad
4

Sie möchten, dass Ihre Ergebnisse klar definiert und wiederholbar sind. Dazu müssen Sie mit bekannten Daten arbeiten, damit Sie sowohl Ihre Normalfälle als auch Ihre Grenzfälle klar definieren können. In meiner Arbeit ist dies immer ein bestimmter Server und ein bestimmter Datensatz, sodass im Unit-Testing-Modul die Verbindungszeichenfolge integriert ist. Andere bevorzugen die Verwendung einer Verbindungszeichenfolge aus dem Unit-Testing-Projekt. Ich habe noch nie jemanden gesehen, der die Verwendung der Konfigurationsdatei der Website empfohlen hat! (Entwicklung oder anders)

Mark Brittingham
quelle
1
Das ist sehr sinnvoll. Was ist also die Lösung, um die Verbindungszeichenfolgen zum Testen in meine App zu integrieren?
ilivewithian
Entweder die Verbindungszeichenfolge, die für Ihre Testumgebung spezifisch ist, hart codieren (dies riecht schlecht, ist aber sehr praktisch, da es nichts mit bereitstellbarem Code zu tun hat) oder Sie verwenden eine Konfigurationsdatei, die speziell für Ihr Unit-Testmodul definiert wurde, wie Gerrie vorgeschlagen hat .
Mark Brittingham
1
Nur um zu betonen: Ich schlage nicht vor, dass Sie jemals eine Datenbankverbindungszeichenfolge in Code fest codieren, der bereitgestellt wird! Ich habe eine bestimmte Datenbank auf einem bestimmten Server, die ich immer für Unit-Tests verwende. Vor dem Testen führe ich ein Skript aus, das sicherstellt, dass sich die Datenbank im entsprechenden Zustand befindet.
Mark Brittingham
1

Wenn Sie eine Verbindungszeichenfolge benötigen, schreiben Sie keinen Komponententest (vorausgesetzt, Sie verwenden die Verbindungszeichenfolge, um zur Datenbank zu gelangen). Unit-Tests dürfen nicht mit der Außenumgebung interagieren. Sie sollten alle nach jedem Check-in ausführen, damit sie besser mit Lichtgeschwindigkeit ausgeführt werden.

Für einen Komponententest möchten Sie Ihren Code von Ihrer Datenbank isolieren. Ändern Sie Ihre Tests (und ggf. den Code, den Sie testen) so, dass Sie zum Testen nicht in die Datenbank gehen müssen.

Serhat Ozgel
quelle
1
Schlagen Sie also vor, dass ich keinen Code teste, der auf eine Datenbank zugreift?
ilivewithian
3
Nein. Ihr Code darf niemals auf die Datenbank zugreifen (es sei denn, Sie schreiben ein Datenbankframework). Stattdessen übergeben Sie ein Objekt an Ihren Code, der auf die Datenbank zugreift. In Ihren Komponententests verspotten Sie dieses Objekt, in der Produktion verwenden Sie die eigentliche Datenbankzugriffsklasse.
Serhat Ozgel
23
Ich bin damit grundsätzlich nicht einverstanden. Unit Testing wird aus dem Bereich praktischer, praktischer Tools zur Verbesserung Ihres Codes herausgenommen und in eine Abstraktion verwandelt, die von künstlichen Grenzen umgeben ist.
Mark Brittingham
3
Die Datenbankfunktionalität kann mit Integrationstests und nicht mit Komponententests getestet werden. Und Sie können diese von Ihren Unit-Tests trennen, sodass Sie Unit-Tests nach jedem Check-in und Ihre Integrationstests nach jedem täglichen Build oder wann immer Sie möchten ausführen.
Serhat Ozgel
6
Ich muss Mark Brittingham hier zustimmen. Ich weiß, dass die Puristen sagen werden, dass Sie Daten verspotten müssen, aber was ist, wenn der größte Teil Ihres Codes von einer Datenbank zurückgegebene Datensatzzeilen iteriert? Wenn Sie ein Scheinobjekt haben, testen Sie nur "imaginären" Code, der ausschließlich zum Testen von Einheiten geschrieben wurde.
Henley Chiu