【问题标题】:Problem in casting Generic.List to System.Threading.Task.Generic.List将 Generic.List 转换为 System.Threading.Task.Generic.List 时出现问题
【发布时间】:2018-11-01 11:59:50
【问题描述】:

我正在尝试创建 IMemoryCache.TryGetValue 方法的模拟,但它在遇到 cache.Get(cacheKey) 时返回以下错误:

无法转换 'System.Collections.Generic.List`1[ConnectionsModel]' to type 'System.Threading.Tasks.Task`1[System.Collections.Generic.List`1[ConnectionsModel] 类型的对象

这是模拟:

 private static Mock<IMemoryCache> ConfigureMockCacheWithDataInCache(List<ConnectionsModel> auth0ConnectionsResponse)
 {
        object value = auth0ConnectionsResponse;
        var mockCache = new Mock<IMemoryCache>();
        mockCache
            .Setup(x => x.TryGetValue(
                It.IsAny<object>(), out value
            ))
            .Returns(true);
        return mockCache;
    }

这里是测试方法:

var connectionList = new List<ConnectionsModel>();
var connectionsModel= new ConnectionsModel()
{
     id = "1",
    name = "abc",
    enabled_cons = new List<string>() { "test" }
};
connectionList.Add(connectionsModel);
var mockObject = ConfigureMockCacheWithDataInCache(connectionList);
var sut = new MyService(mockCache.Object);
// Act
var result = await sut.GetConnection(_clientId);

这是它命中的服务:

public async Task<ConnectionsModel> GetConnection(string clientId)
{
    var connections = await _cacheService.GetOrSet("cacheKey", ()=> CallBack());
    var connection = connections.FirstOrDefault();
    return connection;
}
private async Task<List<ConnectionsModel>> CallBack()
{
    string url = url;
    _httpClient.BaseAddress = new Uri(BaseUrl);
    var response = await _httpClient.GetAsync(url);
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsAsync<List<ConnectionsModel>>();
}

以及缓存扩展方法:

   public static T GetOrSet<T>(this IMemoryCache cache, string cacheKey, Func<T> getItemCallback, double cacheTimeout = 86000) where T : class
    {
        T item = cache.Get<T>(cacheKey);
        if (item == null)
        {
            item = getItemCallback();
            cache.Set(cacheKey, item, DateTime.Now.AddSeconds(cacheTimeout));
        }
        return item;
    }

T item = cache.Get&lt;T&gt;(cacheKey); 这一行之后,我得到了上述异常。我该如何解决这个问题?

【问题讨论】:

  • 您正在传递一个任务并尝试将其分配给任务结果的地方。重新检查扩展方法的逻辑

标签: unit-testing asp.net-core moq xunit


【解决方案1】:

考虑创建一个额外的扩展重载以允许使用异步 API

public static async Task<T> GetOrSet<T>(this IMemoryCache cache, string cacheKey, Func<Task<T>> getItemCallback, double cacheTimeout = 86000) where T : class
{
    T item = cache.Get<T>(cacheKey);
    if (item == null)
    {
        item = await getItemCallback();
        cache.Set(cacheKey, item, DateTime.Now.AddSeconds(cacheTimeout));
    }
    return item;
}

【讨论】:

  • 我还根据您的其他答案为这个扩展方法编写了一个模拟。这样好吗?预期对象; var mockCache = new Mock(); var cachEntry = Mock.Of(); mockCache .Setup(x => x.TryGetValue(It.IsAny(),超出预期 )) .Returns(true); mockCache .Setup(x => x.CreateEntry( It.IsAny() )) .Returns(cachEntry);返回模拟缓存;
  • @Ask 乍一看还不错。它对您的测试有用吗?
【解决方案2】:

在您的扩展方法中,您无需等待即可调用getItemCallback()。该 lambda 在您的服务中调用您的 Callback 方法,该方法是异步的,因此这也是异步的。因此,您将item 设置为Task&lt;List&lt;ConnectionsModel&gt;&gt; 并尝试将其作为List&lt;ConnectionsModel&gt; 返回。

item = await getItemCallback();

【讨论】:

  • 但由于扩展不是异步的,因此需要重构。
  • 如何将参数中的 Func getItemCallBack(0 更改为可等待?
  • 您不需要这样做。返回值将是一个Task,它总是可以等待的。但是,您也可以尝试传递异步 lambda async () =&gt; await Callback()
  • 我试过 async () => await Callback() 但结果相同
  • 另外,@Nkosi 是正确的。如果你有一个异步操作,你必须一直异步。这意味着你的扩展方法应该是异步的,任何调用它的东西也需要是异步的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-12
相关资源
最近更新 更多