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設置了“依賴項”,你就不再進行依賴注入了。
- 1 回答
- 0 關注
- 101 瀏覽
添加回答
舉報