是否可以模拟打字稿装饰器?

Posted

技术标签:

【中文标题】是否可以模拟打字稿装饰器?【英文标题】:Is it possible to mock typescript decorator? 【发布时间】:2017-12-19 09:14:06 【问题描述】:

鉴于我有方法装饰器,例如

class Service 
    @LogCall()
    doSomething() 
        return 1 + 1;
        

是否可以在单元测试中模拟 @LogCall 装饰器,因此不会应用或应用模拟逻辑?

我正在寻找任何 typescript 装饰器的通用解决方案,因为可以更新您的装饰器以检查 window.disableLogDecorator 标志或在测试期间将其关闭,但这不是可重用的解决方案。


当然,我们的用例比提供的示例复杂得多 - 我们有 @memoizeSelector 应用于 ngrx/store 选择器,因此只有在更新特定状态部分时才会调用它们。由于我们在测试中模拟状态的方式,@memoizeSelector 会破坏我们的测试,因此理想情况下我们希望禁用它。

【问题讨论】:

是的,这是可能的,但您需要模拟导出装饰器的模块。你可以使用你的模块加载器来做到这一点,只要它足够灵活。例如,SystemJS 让你很容易做到这一点。请记住,装饰器只是一个函数。 【参考方案1】:

我怀疑装饰器是否有任何模拟。您可以添加静态开关并在装饰器内部处理它或创建可配置的装饰器工厂(但仍然是静态的):

 @LogCall(LogCallFactory)

 export function LogCall(factory:Function):Function
 
    return function(target:Object, propertyKey:string, descriptor:TypedPropertyDescriptor<any>)
    
       return factory(target, propertyKey, descriptor);
    
 

装饰器是在编译时编写的,所以可能可以使用条件编译。

【讨论】:

"装饰器是在编译时编写的,所以可能可以使用条件编译。"这种说法没有意义 你还有什么别的说法吗? 由于该语言不支持条件编译,并且由于装饰器是函数调用的语法糖,因此这个答案没有意义。除了装饰器标准装饰器行为之外,您可能对 typescript 可以提供的可选元数据发出感到困惑,因此认为它们是编译时构造。无论如何,如果从模块中导入某些东西,您可以通过适当地配置捆绑器的加载器来模拟它。 条件编译可以很容易地通过将适当的源文件提供给编译器或捆绑器来实现,它与语言无关。装饰器元数据是在编译时编写的,它定义了目标和装饰器,这就是使用“编写”一词的原因。那么这其中哪一部分没有意义呢? 装饰器不仅仅是元数据。 RE 条件编译:您没有错,实际上您在评论中写的“条件编译可以通过将适当的源文件提供给编译器或捆绑程序非常容易地实现”,应该写在您的答案中_代替术语本身。许多语言都内置了功能,例如预处理器宏,为此,javascript 没有,因此需要加载器或捆绑器来提供此类功能。

以上是关于是否可以模拟打字稿装饰器?的主要内容,如果未能解决你的问题,请参考以下文章

打字稿方法返回未定义的方法装饰器

打字稿装饰器不能使用箭头函数

打字稿装饰器与类继承

打字稿装饰器和箭头函数

带有继承的打字稿装饰器

类装饰器上的打字稿文档-返回“类扩展构造函数”的函数