Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
📦 Microsoft.Extensions.TimeProvider.Testing NuGet paketi, zamana bağlı olan kodun belirlenimci testini sağlayan bir FakeTimeProvider sınıf sağlar. Bu sahte uygulama, testlerinizin içindeki sistem süresini kontrol etmenize ve tahmin edilebilir ve tekrarlanabilir sonuçlar elde etmenizi sağlar.
FakeTimeProvider neden kullanılır?
Geçerli zamana bağlı olan veya zamanlayıcıları kullanan kodu test etme zor olabilir:
- Belirlenemeyen testler: Gerçek zamanlıya bağlı testler tutarsız sonuçlar üretebilir.
- Yavaş testler: Gerçek sürenin geçmesini beklemesi gereken testler, test yürütmeyi önemli ölçüde yavaşlatabilir.
- Yarış koşulları: Zamana bağlı mantık, yeniden oluşturması zor olan yarış koşullarına neden olabilir.
- Uç durumlar: Belirli zamanlarda (gece yarısı veya ay sınırları gibi) zamana dayalı mantığı test etme gerçek zamanlı olarak zordur.
Bu FakeTimeProvider zorlukları şu şekilde ele alır:
- Geçerli saat üzerinde tam denetim sağlama.
- Beklemeden zamanı anında ilerletmenizi sağlar.
- Zaman tabanlı davranışın belirlenimci testini etkinleştirme.
- Uç durumları ve sınır koşullarını test etmeyi kolaylaştırır.
Başlayın
FakeTimeProvider ile başlamaya başlamak için Microsoft.Extensions.TimeProvider.Testing NuGet paketini yükleyin.
dotnet add package Microsoft.Extensions.TimeProvider.Testing
Daha fazla bilgi için bkz. dotnet add package veya .NET uygulamalarında paket bağımlılıklarını yönetme.
Temel kullanım
FakeTimeProvider test için kontrol edilebilir süre sağlamak amacıyla TimeProvider'i genişletir.
var fakeTimeProvider = new FakeTimeProvider();
// Get the current time (defaults to January 1, 2000, midnight UTC).
Console.WriteLine($"Start time: {fakeTimeProvider.GetUtcNow()}");
Belirli bir saatle başlatma
Belirli bir başlangıç saatiyle başlatabilirsiniz FakeTimeProvider :
DateTimeOffset startTime = new(2025, 10, 20, 12, 0, 0, TimeSpan.Zero);
fakeTimeProvider = new FakeTimeProvider(startTime);
Console.WriteLine($"Started at: {fakeTimeProvider.GetUtcNow()}");
Zamanı İlerlet
Belirtilen süre boyunca Advance yöntemini kullanarak zamanı ileri taşır:
// Advance time by 30 minutes.
fakeTimeProvider.Advance(TimeSpan.FromMinutes(30));
Console.WriteLine($"After advancing 30 minutes: {fakeTimeProvider.GetUtcNow()}");
Saat dilimini yapılandırma
Sahte saat sağlayıcısı için yerel saat dilimini ayarlayın:
var timeZoneId = OperatingSystem.IsWindows() ? "Pacific Standard Time" : "America/Los_Angeles";
var pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
fakeTimeProvider.SetLocalTimeZone(pacificTimeZone);
var localTime = fakeTimeProvider.GetLocalNow();
Console.WriteLine($"Local time: {localTime}");
Gecikmeli işlemleri test edin
FakeTimeProvider özellikle gecikmeler içeren test işlemleri için kullanışlıdır:
public class DelayedOperationTests
{
[Fact]
public async Task DelayedOperation_CompletesAfterDelay()
{
// Arrange
var fakeTimeProvider = new FakeTimeProvider();
var operation = new DelayedOperation(fakeTimeProvider);
// Act
Task task = operation.ExecuteAsync(TimeSpan.FromMinutes(5));
// Assert - operation should not be complete yet
Assert.False(task.IsCompleted);
// Advance time by 5 minutes
fakeTimeProvider.Advance(TimeSpan.FromMinutes(5));
// Wait for the task to complete
await task;
// Operation should now be complete
Assert.True(task.IsCompleted);
}
}
public class DelayedOperation(TimeProvider timeProvider)
{
public async Task ExecuteAsync(TimeSpan delay)
{
await Task.Delay(delay, timeProvider);
}
}
Düzenli işlemleri test edin
Zamanlayıcıları kullanarak düzenli aralıklarla yürütülen test işlemleri:
public class PeriodicOperationTests
{
[Fact]
public void PeriodicOperation_ExecutesAtIntervals()
{
// Arrange
var fakeTimeProvider = new FakeTimeProvider();
var counter = new PeriodicCounter(fakeTimeProvider);
counter.Start(TimeSpan.FromSeconds(10));
// Act & Assert
Assert.Equal(0, counter.Count);
// Advance by 10 seconds
fakeTimeProvider.Advance(TimeSpan.FromSeconds(10));
Assert.Equal(1, counter.Count);
// Advance by 20 more seconds
fakeTimeProvider.Advance(TimeSpan.FromSeconds(20));
Assert.Equal(3, counter.Count);
// Clean up
counter.Stop();
}
}
public class PeriodicCounter(TimeProvider timeProvider)
{
private ITimer? _timer;
public int Count { get; private set; }
public void Start(TimeSpan interval)
{
_timer = timeProvider.CreateTimer(
callback: _ => Count++,
state: null,
dueTime: interval,
period: interval);
}
public void Stop()
{
_timer?.Dispose();
}
}
Zamana dayalı iş mantığını test edin
Belirli saatlere veya tarihlere bağlı iş mantığını test edin:
public class SubscriptionTests
{
[Fact]
public void Subscription_ExpiresAfterOneYear()
{
// Arrange
var fakeTimeProvider = new FakeTimeProvider();
var startDate = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero);
fakeTimeProvider.SetUtcNow(startDate);
var subscription = new Subscription(fakeTimeProvider);
subscription.Activate();
// Assert - subscription is active
Assert.True(subscription.IsActive);
// Act - advance time by 11 months
fakeTimeProvider.Advance(TimeSpan.FromDays(30 * 11));
Assert.True(subscription.IsActive);
// Advance time by 2 more months
fakeTimeProvider.Advance(TimeSpan.FromDays(60));
Assert.False(subscription.IsActive);
}
}
public class Subscription(TimeProvider timeProvider)
{
private DateTimeOffset _activationDate;
public void Activate()
{
_activationDate = timeProvider.GetUtcNow();
}
public bool IsActive
{
get
{
DateTimeOffset currentTime = timeProvider.GetUtcNow();
DateTimeOffset expirationDate = _activationDate.AddYears(1);
return currentTime < expirationDate;
}
}
}
Bağımlılık enjeksiyonu ile tümleştirme
Bağımlılık ekleme ile kaydedilen hizmetler için testlerde kullanın FakeTimeProvider :
public class CacheServiceTests
{
[Fact]
public void Cache_ExpiresAfterTimeout()
{
// Arrange
var fakeTimeProvider = new FakeTimeProvider();
var services = new ServiceCollection();
services.AddSingleton<TimeProvider>(fakeTimeProvider);
services.AddSingleton<CacheService>();
ServiceProvider provider = services.BuildServiceProvider();
CacheService cache = provider.GetRequiredService<CacheService>();
// Act
cache.Set("key", "value", TimeSpan.FromMinutes(10));
// Assert - value is present
Assert.True(cache.TryGet("key", out string? value));
Assert.Equal("value", value);
// Advance time beyond expiration
fakeTimeProvider.Advance(TimeSpan.FromMinutes(11));
// Value should be expired
Assert.False(cache.TryGet("key", out _));
}
}
public class CacheService(TimeProvider timeProvider)
{
private readonly Dictionary<string, CacheEntry> _cache = [];
public void Set(string key, string value, TimeSpan expiration)
{
DateTimeOffset expiresAt = timeProvider.GetUtcNow() + expiration;
_cache[key] = new CacheEntry(value, expiresAt);
}
public bool TryGet(string key, out string? value)
{
if (_cache.TryGetValue(key, out CacheEntry? entry))
{
if (timeProvider.GetUtcNow() < entry.ExpiresAt)
{
value = entry.Value;
return true;
}
// Entry expired, remove it
_cache.Remove(key);
}
value = null;
return false;
}
private record CacheEntry(string Value, DateTimeOffset ExpiresAt);
}
En iyi yöntemler
kullanırken FakeTimeProvideraşağıdaki en iyi yöntemleri göz önünde bulundurun:
-
TimeProvider Enjekte Et:
TimeProviderveya DateTime doğrudan kullanmak yerine her zaman DateTimeOffset'yı bağımlılık olarak enjekte edin. Bu, kodunuzu test edilebilir hale getirir. - UTC saatini kullanma: İş mantığınızda UTC saatiyle çalışın ve yalnızca görüntüleme için gerektiğinde yerel saate dönüştürün.
-
Uç durumları test etme: Gece yarısı, ay sınırları, yaz saati geçişleri ve artık yıllar gibi uç durumları test etmek için
FakeTimeProviderkullanın. -
Zamanlayıcıları temizleme: Testlerinizde kaynak sızıntılarını önlemek için ile
CreateTimeroluşturulan zamanlayıcıları atın. - Süreyi kasıtlı olarak ilerlet: Test davranışını net ve öngörülebilir hale getirmek için testlerinizde süreyi açıkça ilerletin.
-
Gerçek ve sahte zamanı karıştırmaktan kaçının: Aynı testte gerçek
TimeProvider.SystemileFakeTimeProviderkarıştırmayın, çünkü bu öngörülemeyen davranışlara yol açabilir.
Ayrıca bakınız
- TimeProvider
- .NET'te birim testi
- .NET'te bağımlılık enjeksiyonu