gpt4 book ai didi

c# - XUnit 如何模拟 IMemoryCache ASP.NET Core

转载 作者:行者123 更新时间:2023-11-30 22:58:05 25 4
gpt4 key购买 nike

我知道 IMemoryCache.Set 是一个扩展方法,所以它不能被模拟。人们已经为这种情况提供了解决方法,例如 NKosi here 的解决方法。 .我想知道如何为我的 MemoryCache 返回一个值的数据访问层实现这一点,当找不到它时,它从数据库获取数据,将其设置为 MemoryCache 并返回所需的值。

    public string GetMessage(int code)
{
if(myMemoryCache.Get("Key") != null)
{
var messages= myMemoryCache.Get<IEnumerable<MyModel>>("Key");
return messages.Where(x => x.Code == code).FirstOrDefault().Message;
}

using (var connection = dbFactory.CreateConnection())
{
var cacheOptions = new MemoryCacheEntryOptions { SlidingExpiration = TimeSpan.FromHours(1) };
const string sql = @"SELECT Code, Message FROM MyTable";

var keyPairValueData = connection.Query<KeyPairValueData>(sql);

myMemoryCache.Set("Key", keyPairValueData, cacheOptions );

return keyPairValueData.Where(x => x.Code == code).FirstOrDefault().Message;
}
}

以下是我的单元测试 - 当然它不起作用,因为我无法模拟 IMemoryCache

    [Fact]
public void GetMessage_ReturnsString()
{
//Arrange
// Inserting some data here to the InMemoryDB

var memoryCacheMock = new Mock<IMemoryCache>();

//Act
var result = new DataService(dbConnectionFactoryMock.Object, memoryCacheMock.Object).GetMessage(1000);

//assert xunit
Assert.Equal("Some message", result);
}

最佳答案

我要说的第一件事是为什么不使用真正的内存缓存?它会更好地验证行为并且不需要模拟它:

// Arrange
var memCache = new MemoryCache("name", new NameValueCollection());

//Act
var result = new DataService(dbConnectionFactoryMock.Object, memCache).GetMessage(1000);

// Assert: has been added to cache
memCache.TryGetValue("Key", out var result2);
Assert.Equal("Some message", result2);

// Assert: value is returned
Assert.Equal("Some message", result);

如果你真的想模拟它,这里有一个关于如何做到这一点的指南:

因为它是一个扩展方法,所以你需要确保它可以被原样调用。在您的情况下,扩展方法将调用模拟。由于您没有提供预期的行为,因此它可能会失败。

您需要查看扩展方法的代码,检查它访问的内容,然后确保您的模拟符合预期行为。该代码可在此处获得: https://github.com/aspnet/Caching/blob/master/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs#L77

这是代码:

public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, MemoryCacheEntryOptions options)
{
using (var entry = cache.CreateEntry(key))
{
if (options != null)
{
entry.SetOptions(options);
}

entry.Value = value;
}

return value;
}

因此,从那里,您可以看到它访问 CreateEnty 并期望从中获得一个对象。然后它调用 SetOptions 并在条目上分配 Value

你可以这样模拟它:

var entryMock = new Mock<ICacheEntry>();
memoryCacheMock.Setup(m => m.CreateEntry(It.IsAny<object>())
.Returns(entryMock.Object);

// maybe not needed
entryMock.Setup(e => e.SetOptions(It.IsAny<MemoryCacheEntryOptions>())
...

执行此操作时,将在模拟上调用扩展方法并返回模拟条目。您可以修改实现并使其执行任何您想要的操作。

关于c# - XUnit 如何模拟 IMemoryCache ASP.NET Core,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53223316/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com