伪造第三方库中的扩展方法

单脚意志

我写了一种无法测试的方法吗?由于我正在使用的库有一个重要的方法,可以实现为扩展方法,所以我似乎无法伪造它。因此,无法测试我的方法。

首先,我将列出要测试的方法的截短版本。然后,我将阐述使用FakeItEasy进行伪造的尝试。

该方法使用缓存,它是对缓存库中静态方法的调用,LazyCache而我一直在努力进行伪造:

public async Task<BassRuleEditModel> GetBassRuleEditModel(
    int facilityId,
    int criteriaId,
    int bassRuleId,
    BassRuleEditDto bassRuleEditDto)
{
    var url = _bassRuleService.GetServiceConnectionForFacility(facilityId).Url;
    var dto = bassRuleEditDto ?? _bassRuleService.GetBassRuleEditDto(bassRuleId);

    var bassRuleEditModel = new BassRuleEditModel
    {                
        ...
        LocationList = await GetLocations(url),
        ...
    };

    ...

    return bassRuleEditModel;
}


private async Task<IEnumerable<SelectListItem>> GetLocations(string url)
{
    var cacheKey = string.Concat(CacheKeys.Location, url);

    var selectList = await _appCache.GetOrAddAsync(cacheKey, async () =>
        {
            return new SelectList(await _tasksAndPrioritiesService.ReturnLocationsAsync(url), NameProperty, NameProperty);
        }
    , CacheKeys.DefaultCacheLifetime);

    return selectList;
}

GetOrAddAsync方法是扩展方法。
我只想让假货从缓存中退回一个空的SelectList

请注意,AppCache和所有依赖项都是使用构造函数注入注入的。

我编写的单元测试(在这里我试图伪造)AppCache是:

[Fact]
public async Task Un_Named_Test_Does_Stuff()
{
    var url = "http://somesite.com";
    var referrer = new Uri(url);
    var facilityId = GetRandom.Id();
    var serviceConnectionDto = new ServiceConnectionDto
    {
        Url = "http://google.com" // this url does not matter
    };

    var cacheKey = string.Concat(CacheKeys.Location, serviceConnectionDto.Url);

    A.CallTo(() => _bassRuleService.GetServiceConnectionForFacility(facilityId)).Returns(serviceConnectionDto);
    A.CallTo(() => _urlHelper.Content("~/ServiceSpec/ListView")).Returns(url);
    A.CallTo(() => _appViewService.GetReferrer(url)).Returns(referrer);
    A.CallTo(() => _appCache.GetOrAddAsync(cacheKey, A<Func<Task<SelectList>>>.Ignored))
        .Returns(Task.FromResult(new SelectList(Enumerable.Empty<SelectListItem>().ToList())));

    var editModel = await
        _bassRuleService.GetBassRuleEditModel(GetRandom.Int32(),
            GetRandom.Int32(),
            GetRandom.Int32(),
            null
            );

    var path = editModel.Referrer.AbsolutePath;

    editModel.Referrer.AbsolutePath.ShouldBe(referrer.AbsolutePath);
}

我在测试的构造函数中创建伪造品(使用xUnit):

public BassRuleQueryServiceTests()
{
    _currentUser = A.Fake<ICurrentUser>();
    _bassRuleService = A.Fake<IBassRuleService>();
    _tasksAndPrioritiesService = A.Fake<ITasksAndPrioritiesService>();
    _appViewService = A.Fake<IAppViewService>();
    _urlHelper = A.Fake<IUrlHelper>();
    _applicationDateTime = A.Fake<IApplicationDateTime>();
    _appCache = new MockCacheService();
}    

运行测试的错误是:

消息:FakeItEasy.Configuration.FakeConfigurationException:当前代理生成器无法为以下方法拦截方法LazyCache.AppCacheExtenions.GetOrAddAsync 1[Microsoft.AspNetCore.Mvc.Rendering.SelectList](LazyCache.IAppCache cache, System.String key, System.Func1 [System.Threading.Tasks.Task`1 [Microsoft.AspNetCore.Mvc.Rendering.SelectList]] addItemFactory)原因:-扩展方法是静态的,因此无法被拦截。

我得到的事实是,伪造静态方法未启用。我正在寻找解决方案。

我是否需要向库作者施加压力,使其不要使用扩展方法?(令人发指的问题)

干杯

托马斯·列夫斯克

正如您已经正确指出的那样,扩展是静态方法,并且不能伪造静态方法。

扩展方法通常只是包装器,以简化对其扩展类型的操作。似乎是这种情况。GetOrAddAsync您要调用扩展方法最终将调用IAppCache.GetOrAddAsync方法因此,您应该改为伪造方法。

A.CallTo(() => _appCache.GetOrAddAsync(cacheKey, A<Func<ICacheEntry, Task<SelectList>>>.Ignored))
        .Returns(new SelectList(Enumerable.Empty<SelectListItem>().ToList()));

这不是很方便,因为这意味着您需要知道扩展方法的作用,但是没有办法解决(除了在库周围创建抽象层之外,但是LazyCache已经是Microsoft.Extensions.Caching.Memory的抽象。 ..)

(顺便说一句,您不需要Task.FromResult;该Returns方法具有重载,T当您配置返回a的方法时,它会接受a Task<T>


同样,如果您仍然要返回空序列,则根本不需要配置该方法。FakeItEasy的默认行为是返回一个IEnumerable<SelectListItem>为空的虚拟对象。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在AngularJs中扩展第三方库的最佳方法

来自分类Dev

在AngularJs中扩展第三方库的最佳方法

来自分类Dev

在Pelican中安装第三方Markdown扩展

来自分类Dev

扩展第三方接口

来自分类Dev

如何允许第三方扩展我的Java库中的类

来自分类Dev

如何允许第三方扩展我的Java库中的类

来自分类Dev

如何向第三方库添加方法

来自分类Dev

获取Java中的第三方库版本

来自分类Dev

在Prestashop中安装第三方库

来自分类Dev

EJB-JAR中的第三方库

来自分类Dev

避免在Veracode中扫描第三方库

来自分类Dev

Singleton与第三方库

来自分类Dev

第三方库的使用

来自分类Dev

在Java Play Framework中扩展默认访问第三方方法

来自分类Dev

在Ember CLI中访问第三方库(例如D3)的正确方法?

来自分类Dev

第三方库中的通用方法限制规避

来自分类Dev

如何测试仅使用第三方库中的操作的Callable方法?

来自分类Dev

如何使用正确的dll文件在Cython C扩展中启用第三方C库?

来自分类Dev

浏览器扩展-如何在background.js文件中包含第三方库

来自分类Dev

如何从库扩展第三方打字稿界面?

来自分类Dev

如何在现有的第三方扩展中重写/扩展Magento类

来自分类Dev

Explorer命名空间扩展-在第三方应用程序中输入Save的方法是什么?

来自分类Dev

编写可选依赖第三方库的库

来自分类Dev

扩展第三方zend Framework 2模块

来自分类Dev

Typescript 第三方定义文件 - 类缺少方法定义 - 如何扩展定义?

来自分类Dev

在第三方库中访问金字塔数据库会话

来自分类Dev

在静态库中包含第三方库(例如:AFNetworking)

来自分类Dev

在cgo库中链接第三方静态库

来自分类Dev

如何将Codeigniter中的sendgrid api库用作第三方库

Related 相关文章

热门标签

归档