Wolę mieć klasy, które wykorzystują czas, w rzeczywistości opierają się na interfejsie, takim jak
interface IClock
{
DateTime Now { get; }
}
Z konkretną realizacją
class SystemClock: IClock
{
DateTime Now { get { return DateTime.Now; } }
}
Następnie, jeśli chcesz, możesz dostarczyć do testowania dowolny inny rodzaj zegara, taki jak
class StaticClock: IClock
{
DateTime Now { get { return new DateTime(2008, 09, 3, 9, 6, 13); } }
}
Dostarczanie zegara do klasy, która na nim polega, może wiązać się z pewnym narzutem, ale może to być obsługiwane przez dowolną liczbę rozwiązań iniekcji zależności (przy użyciu kontenera Inversion of Control, zwykłego wstrzyknięcia starego konstruktora / ustawiacza lub nawet statycznego wzorca bramy ).
Inne mechanizmy dostarczania obiektu lub metody, które zapewniają pożądane czasy, również działają, ale myślę, że kluczową rzeczą jest unikanie resetowania zegara systemowego, ponieważ spowoduje to tylko ból na innych poziomach.
Ponadto używanie go DateTime.Now
i uwzględnianie w obliczeniach nie tylko nie wydaje się właściwe - pozbawia Cię możliwości testowania określonych godzin, na przykład jeśli odkryjesz błąd, który występuje tylko w pobliżu granicy północy lub we wtorki. Korzystanie z bieżącego czasu nie pozwoli Ci przetestować tych scenariuszy. A przynajmniej nie kiedy chcesz.
UtcNow
należy go użyć, a następnie odpowiednio dostosować do obaw związanych z kodem, np. Logiki biznesowej, interfejsu użytkownika itp. Manipulowanie datą i czasem w różnych strefach czasowych jest polem minowym, ale najlepszym pierwszym krokiem do przodu jest zawsze zacząć od Czas UTC.Ayende Rahien stosuje metodę statyczną, która jest raczej prosta ...
źródło
Myślę, że utworzenie oddzielnej klasy zegara dla czegoś prostego, takiego jak uzyskanie aktualnej daty, jest trochę przesadą.
Możesz przekazać dzisiejszą datę jako parametr, aby móc wprowadzić inną datę w teście. Ma to dodatkową zaletę, że Twój kod jest bardziej elastyczny.
źródło
Używanie Microsoft Fakes do tworzenia podkładek jest naprawdę łatwym sposobem na zrobienie tego. Załóżmy, że mam następującą klasę:
W programie Visual Studio 2012 możesz dodać fałszywy zestaw do projektu testowego, klikając prawym przyciskiem myszy zestaw, dla którego chcesz utworzyć podróbki / podkładki, i wybierając opcję „Dodaj fałszywy zespół”
Wreszcie, oto jak wyglądałaby klasa testowa:
źródło
Kluczem do pomyślnego testowania jednostkowego jest oddzielenie . Musisz oddzielić interesujący kod od jego zewnętrznych zależności, aby można go było przetestować w izolacji. (Na szczęście programowanie sterowane testami tworzy oddzielony kod).
W tym przypadku Twoim zewnętrznym jest bieżący DateTime.
Moja rada jest taka, aby wyodrębnić logikę, która zajmuje się DateTime, do nowej metody lub klasy lub cokolwiek, co ma sens w twoim przypadku, i przekazać DateTime w. Teraz twój test jednostkowy może przekazać dowolny DateTime w celu uzyskania przewidywalnych wyników.
źródło
Kolejny wykorzystujący Microsoft Moles ( framework Isolation dla .NET ).
źródło
Sugerowałbym użycie wzorca IDisposable:
Szczegółowo opisane tutaj: http://www.lesnikowski.com/blog/index.php/testing-datetime-now/
źródło
Prosta odpowiedź: porzuć System.DateTime :) Zamiast tego użyj NodaTime i jego biblioteki testowej: NodaTime.Testing .
Czytaj dalej:
źródło
Możesz wstrzyknąć klasę (lepiej: metodę / delegata ), której używasz
DateTime.Now
w testowanej klasie. MająDateTime.Now
być wartością domyślną i ustawiać ją tylko podczas testowania na metodę fikcyjną, która zwraca wartość stałą.EDYCJA: Co powiedział Blair Conrad (ma kod do obejrzenia). Z wyjątkiem tego, że wolę delegatów do tego, ponieważ nie zaśmiecają twojej hierarchii klas takimi rzeczami jak
IClock
...źródło
Tak często spotykałem się z tą sytuacją, że stworzyłem prosty nuget, który ujawnia właściwość Now poprzez interfejs.
Wdrożenie jest oczywiście bardzo proste
Więc po dodaniu nuget do mojego projektu mogę go używać w testach jednostkowych
Możesz zainstalować moduł bezpośrednio z GUI Nuget Package Manager lub używając polecenia:
A kod do Nuget jest tutaj .
Przykład użycia z Autofac można znaleźć tutaj .
źródło
Czy rozważałeś użycie kompilacji warunkowej do kontrolowania tego, co dzieje się podczas debugowania / wdrażania?
na przykład
Jeśli to się nie powiedzie, chcesz ujawnić właściwość, aby móc nią manipulować, to wszystko jest częścią wyzwania związanego z pisaniem testowalnego kodu, z czym obecnie się zmagam: D
Edytować
Duża część mnie wolałaby podejście Blaira . Pozwala to na „podłączanie na gorąco” części kodu, aby ułatwić testowanie. Wszystko to jest zgodne z zasadą projektową, hermetyzacja tego, co zmienia kod testowy, nie różni się od kodu produkcyjnego, po prostu nikt nigdy nie widzi go na zewnątrz.
Tworzenie i interfejs może wydawać się jednak pracochłonne w tym przykładzie (dlatego zdecydowałem się na kompilację warunkową).
źródło
DateTime
„sNow
iToday
itp