Jak wykombinować system plików w C# do testów jednostkowych?

Czy są jakieś biblioteki lub metody do tworzenia testów jednostkowych w C# ? W moim obecnym przypadku mam metody, które sprawdzają, czy dany plik istnieje i odczytują datę utworzenia. W przyszłości będę potrzebował więcej.

Author: pupeno, 2009-07-06

13 answers

Edit: zainstaluj pakiet NuGetSystem.IO.Abstractions.

Ten pakiet nie istniał, gdy odpowiedź ta została pierwotnie zaakceptowana. Oryginalna odpowiedź znajduje się w kontekście historycznym poniżej:

Możesz to zrobić tworząc interfejs:

interface IFileSystem {
    bool FileExists(string fileName);
    DateTime GetCreationDate(string fileName);
}

I stworzenie "prawdziwej" implementacji, która wykorzystuje System.IO.File.Exists() itd. Możesz następnie wyśmiewać ten interfejs za pomocą szyderczy framework; polecam Moq .

Edit: ktoś to zrobił i uprzejmie umieściłem go online tutaj .

Użyłem tego podejścia, aby wyśmiewać DateTime.UtcNow w IClock interfejs (naprawdę bardzo przydatny dla naszych testów, aby móc kontrolować przepływ czasu!), a bardziej tradycyjnie ISqlDataAccess interfejs.

Innym podejściem może być użycie TypeMock , pozwala to na przechwytywać połączenia do klas i usuwać je. To jednak kosztuje pieniądze, i musiałby być zainstalowany na komputerach całego zespołu i Twój build server, aby uruchomić, również, to najwyraźniej nie będzie działać dla plik System. IO., ponieważ nie może stubować pliku mscorlib .

Można również po prostu zaakceptować, że niektóre metody nie są testowane jednostkowo i przetestować je w osobnym, wolno działającym teście integracji/systemu Apartament.

 123
Author: Matt Howells,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-22 10:53:33

Install-Package System. IO. abstrakcje

Ta urojona biblioteka istnieje teraz, istnieje pakiet NuGet dla System. IO. Abstractions , który abstrakuje System.IO przestrzeń nazw.

Istnieje również zestaw pomocników testowych, System. IO. Abstractions. TestingHelpers, który - w momencie pisania-jest tylko częściowo zaimplementowany, ale jest bardzo dobrym punktem wyjścia.

 73
Author: Binary Worrier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-05 09:57:19

Prawdopodobnie będziesz musiał zbudować umowę, aby określić, czego potrzebujesz od systemu plików, a następnie napisać owijkę wokół tych funkcji. W tym momencie będziesz mógł wyśmiać lub stubować implementację.

Przykład:

interface IFileWrapper { bool Exists(String filePath); }

class FileWrapper: IFileWrapper
{
    bool Exists(String filePath) { return File.Exists(filePath); }        
}

class FileWrapperStub: IFileWrapper
{
    bool Exists(String filePath) 
    { return (filePath == @"C:\myfilerocks.txt"); }
}
 9
Author: Joseph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-14 15:43:23

Moim zaleceniem jest użycie http://systemwrapper.codeplex.com/ ponieważ zapewnia on wrappery dla najczęściej używanych typów w przestrzeni nazw systemu

 5
Author: adeel41,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-02 15:41:52

Natknąłem się na następujące rozwiązania:

  • Pisz testy integracyjne, Nie testy jednostkowe. Aby to zadziałało, potrzebujesz prostego sposobu na utworzenie folderu, w którym możesz zrzucać rzeczy bez martwienia się o zakłócanie innych testów. Mam prostą klasę TestFolder , która może stworzyć unikalny folder dla każdej metody testowej.
  • Napisz plik System. IO. czyli Utwórz IFile.cs . Uważam, że używanie tego często kończy się testami, które po prostu udowadniają, że możesz pisz wyśmiewające instrukcje, ale używaj ich, gdy użycie IO jest niewielkie.
  • zbadaj warstwę abstrakcji i wyodrębnij plik IO z klasy. Tworzenie interfejsu do tego. Pozostała część wykorzystuje testy integracyjne (ale będzie to bardzo małe). Różni się to od powyższego tym, że zamiast robić plik.Przeczytaj piszesz intencje, powiedz ioThingie.loadSettings ()
  • System. IO. Abstractions . jeszcze z tego nie korzystałem, ale to jest ten, który najbardziej podoba mi się w grze z.

Kończę używając wszystkich powyższych metod, w zależności od tego, co piszę. Ale przez większość czasu myślę, że abstrakcja jest zła, kiedy piszę testy jednostkowe, które trafiły w IO.

 3
Author: Michael Lloyd Lee mlk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-18 12:06:14

Trudno byłoby wyśmiewać system plików w teście, ponieważ API plików. NET nie są tak naprawdę oparte na interfejsach lub rozszerzalnych klasach, które mogłyby być wyśmiewane.

Jednakże, jeśli masz własną warstwę funkcjonalną, aby uzyskać dostęp do systemu plików, możesz to sfałszować w teście jednostkowym.

Jako alternatywę dla wyśmiewania, rozważ po prostu utworzenie folderów i plików, których potrzebujesz w ramach konfiguracji testowej, i usunięcie ich w metodzie teardown.

 1
Author: LBushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-06 14:55:30

Nie jestem pewien, jak zrobiłbyś makietę systemu plików. Co można zrobić, to napisać konfigurację urządzenia testowego, który tworzy folder, itp. z niezbędną strukturą do badań. Metoda teardown wyczyściłaby go po uruchomieniu testów.

Edited to add: myśląc o tym trochę więcej, nie sądzę, że chcesz wyśmiewać system plików, aby przetestować tego typu metody. Jeśli wyśmiewasz system plików, aby zwrócił true, jeśli dany plik istnieje i użyj go w teście metody, która sprawdza, czy ten plik istnieje, więc niczego nie testujesz. Gdzie wyśmiewanie systemu plików byłoby przydatne, jeśli chcesz przetestować metodę, która była zależna od systemu plików, ale aktywność systemu plików nie była integralna z testowaną metodą.

 1
Author: Jamie Ide,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-06 15:01:06

Odpowiadając na twoje konkretne pytanie: Nie, Nie ma bibliotek, które pozwoliłyby ci na wywołania I/O plików (o których wiem). Oznacza to, że "prawidłowe" testowanie jednostkowe typów będzie wymagało uwzględnienia tego ograniczenia przy definiowaniu typów.

Krótka notka o tym, jak definiuję "właściwy" test jednostkowy. Uważam, że testy jednostkowe powinny potwierdzać, że otrzymujesz oczekiwane dane wyjściowe (np. wyjątek, wywołanie metody itp.) pod warunkiem, że są znane dane wejściowe. Pozwala to na warunki testu jednostkowego można skonfigurować jako zestaw wejść i / lub stanów wejściowych. Najlepszym sposobem, jaki znalazłem, aby to zrobić, jest użycie usług opartych na interfejsie i iniekcji zależności, tak aby każda odpowiedzialność poza typem była dostarczana za pośrednictwem interfejsu przekazywanego przez konstruktor lub właściwość.

Więc, mając to na uwadze, wróćmy do twojego pytania. Wyśmiewałem wywołania systemu plików, tworząc interfejs IFileSystemService wraz z implementacją FileSystemService, która jest po prostu fasadą nad systemem plików mscorlib metody. Mój kod używa wtedy IFileSystemService zamiast typów mscorlib. To pozwala mi podłączyć mój standard FileSystemService, gdy aplikacja jest uruchomiona lub mock IFileSystemService w moich testach jednostkowych. Kod aplikacji jest taki sam niezależnie od sposobu jego uruchomienia, ale podstawowa infrastruktura pozwala na łatwe testowanie tego kodu.

Przyznaję, że używanie wrappera wokół obiektów systemu plików mscorlib jest uciążliwe, ale w tych konkretnych scenariuszach warto wykonać dodatkową pracę jako testowanie staje się o wiele łatwiejsze i bardziej niezawodne.

 1
Author: akmad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-06 17:45:29

Tworzenie interfejsu i wyśmiewanie go do testowania jest najczystszym sposobem. Jednak jako alternatywę yo może spojrzeć na Microsoft Moles framework.

 1
Author: Konamiman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-18 11:31:15

Możesz to zrobić używając Microsoft Fakes bez konieczności zmiany kodu, na przykład dlatego, że był już zamrożony.

Najpierw Wygeneruj fałszywy zestaw dla systemu.dll-lub jakikolwiek inny pakiet, a następnie mock oczekiwanych zwrotów jak w:

using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
     System.IO.Fakes.ShimFile.ExistsString = (p) => true;
     System.IO.Fakes.ShimFile.ReadAllTextString = (p) => "your file content";

      //Your methods to test
}
 1
Author: Bahadır İsmail Aydın,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 02:41:58

Powszechnym rozwiązaniem jest użycie abstrakcyjnego API systemu plików( jak Apache Commons VFS dla Javy): Cała logika aplikacji używa API i unit test jest w stanie naśladować prawdziwy system plików z implementacją stub (emulacja w pamięci lub coś w tym stylu).

Dla C# istnieje podobne API: NI.Vfs , który jest bardzo podobny do Apache VFS V1. Zawiera domyślne implementacje zarówno dla lokalnego systemu plików, jak i systemu plików w pamięci (ostatnia może być używana w testach jednostkowych z pudełka).

 0
Author: Vitaliy Fedorchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-10 13:31:51

Zgadzam się z odpowiedzią Jamiego Ide. Nie próbuj wyśmiewać rzeczy, których nie napisałeś. Będą różne zależności, o których nie wiedziałeś - zamknięte klasy, nie wirtualne metody itp.

Innym podejściem byłoby owinięcie metod appopiate czymś, co jest dające się wyśmiewać. na przykład utwórz klasę o nazwie FileWrapper, która umożliwia dostęp do metod plików, ale jest czymś, co możesz wymazać.

 -1
Author: gbanfill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-06 14:55:47

Obecnie używamy zastrzeżonego silnika danych, a jego API nie jest wystawione jako interfejsy, więc trudno nam przetestować nasz kod dostępu do danych. Potem poszedłem z Mattem i Josephem podejście też.

 -1
Author: Tien Do,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-17 09:17:47