1 回答
TA贡献1853条经验 获得超18个赞
通过使缓存静态化,您关闭了一些门。
快速而肮脏的解决方案:
因为你不能构造函数注入你的存储库,下一个最好的办法就是将它传递给你的静态方法。
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);
优选解决方案:
我假设您的存储库负责会话管理(因此使用 IDisposable 接口)。如果有一种方法可以将存储库接口与某些实现可能需要释放的任何资源分开,您可以转向构造函数注入方法。
您的代码将类似于以下内容:
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);
}
您还可以考虑反转缓存和存储库之间的依赖关系。换句话说,您的存储库实现可以有一个缓存。这允许您更动态地选择缓存策略。例如,您可能有以下任一情况:
var repo = new ContactRepository(new MemoryCache<Contact>())
或者
var repo = new ContactsRepository(new NullCache<Contact>())<-- 如果您在某些情况下不需要缓存。
这种方法意味着存储库的使用者不需要知道或关心数据的来源。这使您可以在一开始就不需要存储库的情况下测试缓存机制。当然,如果您想测试存储库,则需要为其提供缓存策略。
遵循这种方法还可以让您获得一个相当快速的解决方案,因为您可以用这样的类包装现有的静态缓存:
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
}
}
您的存储库需要做一些工作才能使其在访问数据库/文件系统/远程资源之前考虑缓存。
旁注——如果你new设置了“依赖项”,你就不再进行依赖注入了。
- 1 回答
- 0 关注
- 80 浏览
添加回答
举报