【发布时间】:2019-04-01 15:59:37
【问题描述】:
我有一个用于联系人列表的静态异步缓存。在缓存内部,我正在调用我的存储库以从后端获取数据。我想模拟 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);
}
}
最后我希望有这种用法,但我不知道如何更改缓存类,否则任何其他帮助之王都会非常有帮助。
[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 actual = await ContactsCache.GetContactsAsync(It.IsAny<int>(), CancellationToken.None);
CollectionAssert.AreEqual(actual, expected);
}
但它不能工作,我不知道如何正确编写单元测试。
我有很多这样的缓存,我正在使用这样的存储库。在这种情况下,是否有任何标准或最佳实践如何对静态异步缓存进行单元测试以及如何模拟存储库?
【问题讨论】:
-
ContactsCache需要是静态的吗? -
你用的是什么模拟框架?它看起来像起订量,但我不想在问题上贴错标签...
-
为什么还要让类静态?就让它成为一个正常的类。 DependencyInjection 的全部工作是为任何需要它的代码提供缓存类实例。
-
是的,我正在使用起订量
-
我需要让它在很多地方使用静态。它用于缓存目的,将其设置为静态非常有用。我可以把它变成单身,但不确定这是否有帮助。
标签: c# .net unit-testing testing