第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

靜態(tài)異步類的模擬單元測試和依賴注入

靜態(tài)異步類的模擬單元測試和依賴注入

C#
白板的微信 2022-11-21 21:15:29
我有一個用于聯(lián)系人列表的靜態(tài)異步緩存。在緩存內部,我正在調用我的存儲庫以從后端獲取數據。我想模擬 ContactsRepository,但我需要將存儲庫作為參數傳遞并使用依賴注入。根據文檔,它不起作用,因為我需要一個類的實例來使用依賴注入。public interface IContactsCache{    Task<List<Contact>> GetContactsAsync(int inst, CancellationToken ct);}public class ContactsCache : IContactsCache{    private static readonly object _syncRoot = new object();    private static readonly Dictionary<int, Task<List<Contact>>> _contactsTasks = new Dictionary<int, Task<List<Contact>>>();    public static Task<List<Contact>> GetContactsAsync(int inst)    {        return GetContactsAsync(inst, CancellationToken.None);    }    public static async Task<List<Contact>> GetCodeValuesAsync(int inst, CancellationToken ct)    {        Task<List<Contact>> task;        lock (_syncRoot)        {            if (_contactsTasks.ContainsKey(inst) && (_contactsTasks[inst].IsCanceled || _contactsTasks[inst].IsFaulted))            {                _contactsTasks.Remove(inst);            }            if (!_contactsTasks.ContainsKey(inst))            {                _contactsTasks[inst] = Task.Run(async () =>                {                    using (var rep = new ContactsRepository())                    {                        return await rep.LoadAsync(inst, ct).ConfigureAwait(false);                    }                });            }            task = _contactsTasks[inst];        }        var res = await task.ConfigureAwait(false);        lock (_syncRoot)        {            return res != null ? res.ToList() : null;        }    }    Task<List<CodeValue>> IContactsCache.GetContactsAsync(int inst, CancellationToken ct)    {        return GetContactsAsync(inst, ct);    }}最后我希望有這種用法,但我不知道如何更改緩存類或任何其他幫助之王都會非常有幫助。但它行不通,我不知道如何正確編寫單元測試。我在使用此類存儲庫的地方有很多此類緩存。在這種情況下,是否有任何標準或最佳實踐如何對靜態(tài)異步緩存進行單元測試以及如何模擬存儲庫?
查看完整描述

1 回答

?
慕容森

TA貢獻1853條經驗 獲得超18個贊

通過使緩存靜態(tài)化,您關閉了一些門。


快速而骯臟的解決方案:


因為你不能構造函數注入你的存儲庫,下一個最好的辦法就是將它傳遞給你的靜態(tài)方法。


 public static async Task<List<Contact>> GetCodeValuesAsync(IContactRepository repo, int inst, CancellationToken ct)

如果您這樣做,將存儲庫的生命周期管理上移一個級別可能是一個更好的主意。換句話說,將using語句移動到調用者:


using(var repo = new ContactRepository())

{

    await ContactsCache.GetContactsAsync(repo , It.IsAny<int>(), CancellationToken.None);

}

然后在你的測試中你可以這樣做:


var mock = new Mock<IContactsRepository>()

        .Setup(x => x.LoadAsync(It.IsAny<int>(), CancellationToken.None))

        .ReturnsAsync(new List<Contact>(expected));


var actual = await ContactsCache.GetContactsAsync(mock , It.IsAny<int>(), CancellationToken.None);

優(yōu)選解決方案:


我假設您的存儲庫負責會話管理(因此使用 IDisposable 接口)。如果有一種方法可以將存儲庫接口與某些實現(xiàn)可能需要釋放的任何資源分開,您可以轉向構造函數注入方法。


您的代碼將類似于以下內容:


public class ContactsCache : IContactsCache

{

    private readonly IContactRepository contactRepo;


    public ContactsCache(IContactRepository contactRepo)

    {

        this.contactRepo = contactRepo;

    }


    // ...

    return await this.contactRepo.LoadAsync(inst, ct).ConfigureAwait(false);

    // ...

}

您的單元測試將如下所示:


[TestMethod]

public async void GetContactAsync_WhenCalled_ReturnCodeValuesCache()

{

    var expected = new List<Contact>

    {

        new Contact() {Instance = 1, Name = "Test" }

    };


    var mock = new Mock<IContactsRepository>()

        .Setup(x => x.LoadAsync(It.IsAny<int>(), CancellationToken.None))

        .ReturnsAsync(new List<Contact>(expected));


    var cache = new ContactsCache(mock);


    var actual = await cache .GetContactsAsync(It.IsAny<int>(), CancellationToken.None);


    CollectionAssert.AreEqual(actual, expected);

}

您還可以考慮反轉緩存和存儲庫之間的依賴關系。換句話說,您的存儲庫實現(xiàn)可以有一個緩存。這允許您更動態(tài)地選擇緩存策略。例如,您可能有以下任一情況:


var repo = new ContactRepository(new MemoryCache<Contact>())


或者


var repo = new ContactsRepository(new NullCache<Contact>())<-- 如果您在某些情況下不需要緩存。


這種方法意味著存儲庫的使用者不需要知道或關心數據的來源。這使您可以在一開始就不需要存儲庫的情況下測試緩存機制。當然,如果您想測試存儲庫,則需要為其提供緩存策略。


遵循這種方法還可以讓您獲得一個相當快速的解決方案,因為您可以用這樣的類包裝現(xiàn)有的靜態(tài)緩存:


public class MemoryCache : ICachingStrategy<Contact>

{

    public async Task<List<Contact>> GetCodeValuesAsync(int inst, CancellationToken ct) // This comes from the interface

    {

        return await ContactsCache.GetContactsAsync(inst, ct); // Just forward the call to the existing static cache

    }

}

您的存儲庫需要做一些工作才能使其在訪問數據庫/文件系統(tǒng)/遠程資源之前考慮緩存。


旁注——如果你new設置了“依賴項”,你就不再進行依賴注入了。


查看完整回答
反對 回復 2022-11-21
  • 1 回答
  • 0 關注
  • 101 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號