2013-10-15 14 views
6

Jeśli tworzysz systemy, w których procesy biznesowe zależą od tego, o której godzinie jest [1], nie możesz użyć kodu DateTime.Now lub podobnego, ponieważ będziesz musiał przeprowadzić testy w np. Przyszłym Koniec miesiąca lub Koniec roku scenariusze. Zmiana czasu systemu operacyjnego na ogół nie jest opcją w przypadku korzystania z certyfikatów SSL i ze względu na złożoność prawidłowego działania systemu rozproszonego.Wzorzec projektowy dla czasu aplikacji?

Jedną opcją jest utworzenie usługi singleton dostępnej dla wszystkich systemów, która zwraca bieżący czas. W produkcji może zwrócić DateTime.Now iw testach może zwrócić czas gry podobny do 28 lutego w scenariuszu Koniec miesiąca.

Ale czy jest lepszy sposób na zrobienie tego? Jak podejście bardziej zorientowane na bazę danych, ponieważ prowadzi to do lepszej wydajności? A może wstawiłbyś rozproszoną pamięć podręczną? Czy jest jakiś znany wzór projektu?

[1] typowy przykład: procesy biznesowe realizowane przez system ubezpieczeń, rdzeń systemu bankowego, ...

+0

lubię wykorzystanie frameworków takich jak podróbki do kontroli czasu w normalnych testach. Możesz także użyć np. Unity, aby wydobyć czas z kodu produkcyjnego, co oznacza, że ​​wstrzykujesz czas gry w testach i DateTime.Now. Jednak nie można w pełni polegać na tym podejściu, budując większe systemy dla sektora finansowego, ponieważ testy tego typu są często prowadzone przez użytkowników. Zwykły przykład: administrator (może być przedsiębiorcą) przesyła nowy zestaw parametrów biznesowych (takich jak oprocentowanie) do środowiska testowego i chciałby zweryfikować, jak system reaguje z biznesowego punktu widzenia. Muszą być w stanie zmienić czas. –

Odpowiedz

0

I zawarły następujące podejście zadziała:

Testy jednostkowe:

  • ramy Mocking, aby kontrolować czas dowolnie

Testy integracyjne, testy oparte na użytkownikach & produ ction:

  • wstrzykiwania zależności, stosowane do wstrzykiwania podejście testową lub podejście produkcyjne
  • podejście Test: zapytać serwer NTP za to, co jest czas. Ten serwer NTP zostanie podłączony do wszystkich odpowiednich aplikacji, a nie serwerów, które mają własne. Serwer NTP będzie standardowo wyposażony w interfejs, który pozwala programom takim jak portal testowy lub narzędzia administratora zmieniać je w razie potrzeby.
  • podejście Produkcja: zapytać czas systemowy, który jest razem z serwerem NTP podłączony do wszystkich serwerów

Oto kod C# do wywoływania serwera NTP: calling NTP server from C#

Lars

4

Jednym ze sposobów radzenia sobie z tym problemem jest mieć clock interface:

public interface IClock { 
    DateTime Now { get; } 
} 

Używaj tego interfejsu w całym kodzie, zamiast DateTime.Now. W produkcji, będziemy używać jej kanoniczną realizacji (lub wariant UTC):

public class SystemClock implements IClock { 
    public DateTime Now { get { return DateTime.Now; } } 
} 

Można na przykład użyć SystemClock jako domyślne we wszystkich klasach, które potrzebują IClock i pozwalają inne implementacje być wstrzykiwany przez konstruktorów lub seterów.

W testach można utworzyć implementację testową lub wyśmiać ją za pomocą szyderstwa.

2

Możesz sprawdzić, czy używasz Microsoft Fakes, aby osiągnąć to, o czym mówisz.

Zobacz ten nieco zmodyfikowany przykład;

[TestMethod] 
public void TestCurrentYear() 
{ 
    int fixedYear = 2000; 

    // Shims can be used only in a ShimsContext: 
    using (ShimsContext.Create()) 
    { 
     // Arrange: 
     // Shim DateTime.Now to return a fixed date: 
     System.Fakes.ShimDateTime.NowGet = 
     () => 
     { return new DateTime(fixedYear, 1, 1); }; 

     // Act: 
     int year = DateTime.Now.Year; 

     // Assert: 
     Assert.AreEqual(fixedYear, year); 
    } 
} 

Zaletą jest to, że nie trzeba zmieniać żadnego kodu, który używa DateTime, aby był testowalny.

1

Do testów jednostkowych, powinieneś być w stanie odgadnąć wszystko, łącznie z czasem. Niektóre szydercze frameworki (na przykład Microsoft Shims) pozwalają na zastąpienie zachowania DateTime.Now.

Do testowania integracji/systemu, co zrobiłem w przeszłości, używam ustawienia konfiguracyjnego dla każdego komponentu systemowego, który określa przesunięcie datownika dla tego komponentu, które ma być używane z prawdziwym DateTime. Może to być ustawione przez nieudokumentowane ustawienie app.config, gdzie w przypadku nieobecności ustawienia obowiązuje normalne zachowanie. Musisz jednak uważać, aby nie wprowadzać żadnych luk w zabezpieczeniach.