Czy projekt testu jednostkowego może załadować plik app.config aplikacji docelowej?

150

Testuję jednostkowo aplikację .NET (.exe), która używa pliku app.config do ładowania właściwości konfiguracyjnych. Sama aplikacja do testów jednostkowych nie ma pliku app.config.

Kiedy próbuję przetestować jednostkę metody, która wykorzystuje dowolne właściwości konfiguracyjne, zwracają wartość null . Zakładam, że dzieje się tak, ponieważ aplikacja testu jednostkowego nie będzie ładowana w pliku app.config aplikacji docelowej.

Czy istnieje sposób na zastąpienie tego, czy muszę napisać skrypt, aby skopiować zawartość docelowego pliku app.config do lokalnego pliku app.config?

Ten post w pewnym sensie zadaje to pytanie, ale autor tak naprawdę patrzy na to z innej perspektywy niż ja.

EDYCJA: Powinienem wspomnieć, że używam VS08 Team System do moich testów jednostkowych.

Jordan Parmer
źródło

Odpowiedzi:

59

Najprostszym sposobem na to jest dodanie .configpliku w sekcji wdrażania testu jednostkowego.

Aby to zrobić, otwórz .testrunconfigplik z pozycji rozwiązania. W sekcji Wdrażanie dodaj .configpliki wyjściowe z katalogu kompilacji projektu (prawdopodobnie bin\Debug).

Wszystko, co jest wymienione w sekcji wdrażania, zostanie skopiowane do folderu roboczego projektu testowego przed uruchomieniem testów, więc kod zależny od konfiguracji będzie działał poprawnie.

Edycja: zapomniałem dodać, to nie zadziała we wszystkich sytuacjach, więc może być konieczne dołączenie skryptu startowego, który zmienia nazwę danych wyjściowych, .configaby pasowały do ​​nazwy testu jednostkowego.

Jeromy Irvine
źródło
9
O wiele łatwiej jest po prostu dodać plik app.config do projektu testowego - nie musisz wtedy w ogóle bawić się plikiem .testrunconfig.
Rowland Shaw
13
@Rowland, jeśli to zrobisz, musisz zachować dwie kopie pliku app.config. Wolałbym spędzić raz 10 sekund, używając narzędzia .testrunconfig, zamiast pamiętać o aktualizacji app.config w obu miejscach.
Jeromy Irvine
66
Nie możesz po prostu dodać odniesienia, które nie pozwala na kopiowanie? (Dodaj istniejący przedmiot ...)
EFraim
6
Komentarz EFraima powinien być akceptowaną odpowiedzią, jest to znacznie prostsze niż cokolwiek innego.
reggaeguitar
28
W przypadku rozwiązania EFraim: Upewnij się, że używasz opcji „Dodaj jako łącze” z przycisku polecenia. W przeciwnym razie nadal otrzymasz kopię. Ponadto, chociaż kwestia jest specjalnie dla aplikacji .NET, to nie będzie działać dla aplikacji WWW jako aplikacja WWW config ma złą nazwę (web.config, nie app.config)
Rob Von Nesselrode
103

W Visual Studio 2008 dodałem app.configplik do projektu testowego jako istniejący element i wybrałem kopię jako łącze, aby upewnić się, że nie jest zduplikowany. W ten sposób mam tylko jedną kopię w moim rozwiązaniu. Przy kilku projektach testowych jest to naprawdę przydatne!

Dodaj istniejący element

Dodaj jako łącze

bbodenmiller
źródło
7
Doskonała odpowiedź, prosta i obiektywna! +1
Custodio,
2
To najlepsze rozwiązanie i należy je oznaczyć jako odpowiedź.
niaher
4
Aby dodać istniejący element „jako łącze”, należy: „W oknie dialogowym Dodaj istniejący element zlokalizować i wybrać element projektu, który chcesz połączyć”, a następnie: „Z rozwijanej listy przycisku Otwórz wybierz opcję Dodaj jako łącze. "
uriel
To działało świetnie dla mnie. Próbuję wymyślić sytuację, w której to by nie zadziałało… I pomyślałem już wystarczająco dużo. Dzięki!
Dudeman3000
53

Niezależnie od tego, czy używasz Team System Test, czy NUnit , najlepszą praktyką jest utworzenie osobnej biblioteki klas na potrzeby testów. Po prostu dodanie pliku App.config do projektu testowego zostanie automatycznie skopiowane do folderu bin podczas kompilacji .

Jeśli twój kod jest zależny od określonych testów konfiguracji, pierwszy test, który napiszę, sprawdza, czy plik konfiguracyjny jest dostępny ( aby wiedzieć, że nie jestem szalony ):

<configuration>
   <appSettings>
       <add key="TestValue" value="true" />
   </appSettings>
</configuration>

I test:

[TestFixture]
public class GeneralFixture
{
     [Test]
     public void VerifyAppDomainHasConfigurationSettings()
     {
          string value = ConfigurationManager.AppSettings["TestValue"];
          Assert.IsFalse(String.IsNullOrEmpty(value), "No App.Config found.");
     }
}

W idealnym przypadku powinieneś pisać kod w taki sposób, aby obiekty konfiguracyjne były przekazywane do klas. To nie tylko oddziela Cię od problemu z plikiem konfiguracyjnym, ale także umożliwia pisanie testów dla różnych scenariuszy konfiguracji.

public class MyObject
{
     public void Configure(MyConfigurationObject config)
     {
          _enabled = config.Enabled;
     }

     public string Foo()
     {
         if (_enabled)
         {
             return "foo!";
         }
         return String.Empty;
     }

     private bool _enabled;
}

[TestFixture]
public class MyObjectTestFixture
{
     [Test]
     public void CanInitializeWithProperConfig()
     {
         MyConfigurationObject config = new MyConfigurationObject();
         config.Enabled = true;

         MyObject myObj = new MyObject();
         myObj.Configure(config);

         Assert.AreEqual("foo!", myObj.Foo());
     }
}
bryanbcook
źródło
2
Zgadzam się z duchem przejścia w zależności konfiguracji tutaj, wydaje się, że odpowiedź na to pytanie udzielił nie mniej niż Mark Seemann! tutaj: Nieudane testy jednostkowe z powodu braku pliku .config
Shaun
W wierszu brakuje elementu „: string value = ConfigurationManager.AppSettings [" TestValue]; Próbowałem to naprawić, ale musiałbym znaleźć dalsze 5 znaków do naprawienia, aby uzyskać przepełnienie stosu i umożliwić mi edycję.
Jane,
22

Jeśli masz rozwiązanie, które zawiera na przykład aplikację internetową i projekt testowy, prawdopodobnie chcesz, aby projekt testowy używał pliku web.config aplikacji sieci Web.

Jednym ze sposobów rozwiązania tego problemu jest skopiowanie pliku web.config w celu przetestowania projektu i zmiana jego nazwy na app.config.

Innym i lepszym rozwiązaniem jest zmodyfikowanie łańcucha kompilacji i wykonanie automatycznej kopii pliku web.config w celu przetestowania katalogu wyjściowego projektów. Aby to zrobić, kliknij prawym przyciskiem myszy opcję Testuj aplikację i wybierz właściwości. Teraz powinieneś zobaczyć właściwości projektu. Kliknij „Build Events”, a następnie kliknij przycisk „Edit Post-build ...”. Wpisz tam następującą linię:

copy "$(SolutionDir)\WebApplication1\web.config" "$(ProjectDir)$(OutDir)$(TargetFileName).config"

I kliknij OK. (Zauważ, że najprawdopodobniej musisz zmienić WebApplication1 jako nazwę projektu, który chcesz przetestować). Jeśli masz złą ścieżkę do web.config, kopiowanie się nie powiedzie i zauważysz to podczas nieudanej kompilacji.

Edytować:

Aby skopiować z bieżącego projektu do projektu testowego:

copy "$(ProjectDir)bin\WebProject.dll.config" "$(SolutionDir)WebProject.Tests\bin\Debug\App.Config"
Antti
źródło
Naprawdę fajne rozwiązanie. Pomogło mi to uniknąć kopiowania i powielania .configplików. Dzięki za udostępnienie! :)
Leniel Maccaferri
Bardzo fajne rozwiązanie! Wielkie dzięki.
Vin Shahrdar
Niezłe rozwiązanie, ale co się dzieje, gdy główny web.configma tylko odniesienia do .configplików zewnętrznych w tym samym projekcie. Ponieważ ścieżka może wskazywać tylko foldery w tym samym katalogu (co zwykle jest prawdą), podczas uruchamiania testów nie będzie w stanie obsłużyć tych plików zewnętrznych. Masz jakiś pomysł, jak to rozwiązać?
Sugafree
To zadziałało dla mnie: skopiuj „$ (SolutionDir) \ MainProject \ Web.config” „$ (ProjectDir) app.config”
Andrzej,
8

To jest trochę stare, ale znalazłem na to lepsze rozwiązanie. Próbowałem tutaj wybrać wybraną odpowiedź, ale wygląda na to, że .testrunconfig jest już przestarzały.

1. W przypadku testów jednostkowych Wrap the config is a Interface (IConfig)

w przypadku testów jednostkowych konfiguracja naprawdę nie powinna być częścią tego, co testujesz, więc stwórz makietę, którą możesz wstrzyknąć. W tym przykładzie używałem Moq.

Mock<IConfig> _configMock;
_configMock.Setup(config => config.ConfigKey).Returns("ConfigValue");
var SUT = new SUT(_configMock.Object);

2. W celu przeprowadzenia testu integracji dynamicznie dodaj potrzebną konfigurację

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if(config.AppSettings.Settings[configName] != null)
{
    config.AppSettings.Settings.Remove(configName);
}
config.AppSettings.Settings.Add(configName, configValue);
config.Save(ConfigurationSaveMode.Modified, true);
ConfigurationManager.RefreshSection("appSettings");
MichaelChan
źródło
5

To bardzo proste.

  • Kliknij prawym przyciskiem myszy projekt testowy
  • Dodaj -> Istniejący element
  • Możesz zobaczyć małą strzałkę tuż obok przycisku Dodaj
  • Wybierz plik konfiguracyjny i kliknij „Dodaj jako łącze”
Hari Das
źródło
4

Jeśli używasz NUnit, spójrz na ten post . Zasadniczo musisz mieć plik app.config w tym samym katalogu, co plik .nunit.

Cory Foy
źródło
Używam VS08 Team System do moich testów jednostkowych, ale dzięki za wskazówkę NUnit!
Jordan Parmer,
2

Jeśli aplikacja używa ustawienia, takiego jak Asp.net ConnectionString, musisz dodać atrybut HostType do swojej metody, w przeciwnym razie nie będą one ładowane, nawet jeśli masz plik App.Config.

[TestMethod]
[HostType("ASP.NET")] // will load the ConnectionString from the App.Config file
public void Test() {

}
Zyo
źródło
0

Używam NUnit iw katalogu mojego projektu mam kopię mojego App.Config, że zmieniam konfigurację (przykład przekierowuję do testowej bazy danych ...). Musisz go mieć w tym samym katalogu testowanego projektu i wszystko będzie dobrze.

Patrick Desjardins
źródło
0

Nie mogłem uzyskać żadnej z tych sugestii dotyczących pracy z nUnit 2.5.10, więc ostatecznie użyłem funkcji Projekt nUnit -> Edytuj, aby określić plik konfiguracyjny do celu (jak powiedzieli inni, musi znajdować się w tym samym folderze co plik. nunit sam plik). Pozytywną stroną tego jest to, że mogę nadać plikowi konfiguracyjnemu nazwę Test.config, co znacznie wyjaśnia, co to jest i dlaczego)

Jane
źródło
0

Twoje testy jednostkowe są traktowane jako środowisko, które uruchamia kod, aby go przetestować. Jak w każdym normalnym środowisku, masz np. Staging / produkcję. Konieczne może być również dodanie .configpliku do projektu testowego. Obejściem problemu jest utworzenie biblioteki klas i przekonwertowanie jej na projekt testowy przez dodanie niezbędnych pakietów NuGet, takich jak NUnit i NUnit Adapter. działa doskonale zarówno z Visual Studio Test Runner, jak i Resharper, a Twój app.configplik znajduje się w projekcie testowym. wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj

I wreszcie zdebugowałem mój test i wartość z App.config:

wprowadź opis obrazu tutaj

Ben
źródło