2016-08-03 145 views
0

我該如何模擬Azure Redis緩存?我該如何模擬Azure Redis緩存?

我想爲使用Azure Redis緩存的應用程序編寫單元測試。由於我在編寫單元測試代碼時嘲笑和寫作是全新的,因此我正在尋找關於如何開始使用基本腳本來模擬/存儲緩存組件的幫助。

回答

2

使用外部資源(如數據庫,文件和緩存)進行測試是集成測試,非單元。你可以在單元測試中測試的事實是,你的代碼正在調用緩存方法。

所以,首先,你需要一個接口緩存服務。這個接口不僅可以讓你測試你的代碼,還可以讓你使用不同的緩存服務器。

public interface ICache 
{ 
    void Add<T>(string key, TimeSpan lifetime, T value); 

    bool TryGet<T>(string key, out T value); 

    void Remove(string key); 

    . . . 
} 

其次,您需要域代碼來測試:

public class SleepingMembersService 
{ 
    private readonly TimeStamp _lifetime = TimeStamp.FromMinutes(5); 
    private readonly ICache _cache; 
    private readonly INotifier _notifier; 

    public SleepingMembersService(ICache cache, INotifier notifier) 
    { 
     _cache = cache; 
     _notifier = notifier; 
    } 

    private string MakeKey(User user) => $"unsleepingUser{user.Id}"; 

    public void WakeUpIfSleep(IUser user) 
    { 
     var key = MakeKey(user); 
     bool isWaking; 
     if (_cache.TryGet(key, out isWaking) && isWaking) 
      return; 

     notifier.Notify(user.Id, "Wake up!");    
    } 

    public void ConfirmImNotSleeping(IUser user) 
    { 
     var key = MakeKey(user); 
     _cache.Add(key, _lifeTime, true); 
    } 
} 

第三,讓我們做樁緩存:

public class StubCache : ICache 
{ 
    public bool TryGetResult { get; set; } 

    public bool TryGetValue { get; set; } 

    public bool AddValue { get; set; } 

    public TimeStamp LifeTimeValue { get; set; } 

    void Add<T>(string key, TimeSpan lifetime, T value) 
    { 
     LifeTimeValue = lifetime; 
     AddValue = (bool)(object)value; 
    } 

    bool TryGet<T>(string key, out T value) 
    { 
     value = (T)(object)TryGetValue; 
     return TryGetResult; 
    } 

    . . . 
} 

最後,你可以編寫單元測試:

pubic void ConfirmImNotSleeping_WhenCalled_CallsAdd() 
{ 
    var cache = new StubCache<bool>(); 
    var notifier = new StubNotifier(); 
    var service = new SleepingMembersService(cache, notifier); 
    var user = new StubUser(1, "John Doe"); 

    service.ConfirmNotSleeping(user); 

    Assert.IsTrue(cache.AddValue); 
} 

那麼,你已經檢查過該方法ConfirmNotSleeping調用方法Add。現在

,你應該實現ICache對Redis的:

public RedisCache : ICache 
{ 
    private IConnectionMultiplexer connection; 

    public bool TryGet<T>(string key, out T value) 
    { 
     var cache = Connection.GetDatabase(); 

     var rValue = cache.StringGet(key); 
     if (!rValue.HasValue) 
     { 
      value = default(T); 
      return false; 
     } 

     value = JsonConvert.DeserializeObject<T>(rValue); 
     return true; 
    } 

    . . .  
} 

爲了簡化實現存根和嘲笑,你可以使用庫像Moq。這些庫讓你自動生成存根和嘲笑,以達到你的目的。所以你的測試代碼將如下所示:

pubic void ConfirmImNotSleeping_WhenCalled_CallsAdd() 
{ 
    var cacheStub = new Mock<ICache>(); 
    var notifierStub = new Mock<INotifier>(); 
    var service = new SleepingMembersService(cache.Object, notifier.Object); 
    var userStub = new Mock<IUser>(); 

    service.ConfirmNotSleeping(user.Object); 

    cacheStub.Vertify(x => x.Add(It.IsAny<string>(), It.IsAny<TimeStamp>(), true)); 
} 
+0

謝謝你的幫助! 但是,第三步是給出編譯錯誤 - void Add (string key,TimeSpan lifetime,T value) LifeTimeValue = lifetime; AddValue = value; } 由於值的類型是T. –

+0

如果您可以給出一個簡單的set示例並從Redis緩存中獲取對象並隨後獲得測試代碼,那將是非常棒的。謝謝! –

+0

我糾正了方法'Add'和'TryGet'的執行錯誤。關於你的第二個評論:我的回答描述了緩存邏輯的單元問題。如果你想在測試中調用Redis方法,將會有集成測試,而不是單元測試。 –