如何在 Angular 单元测试中模拟/监视导入的函数

Posted

技术标签:

【中文标题】如何在 Angular 单元测试中模拟/监视导入的函数【英文标题】:How to mock/spy an imported function in Angular unit testing 【发布时间】:2018-11-09 08:19:36 【问题描述】:

假设我有一个角度为 6 的组件,其方法 test 返回一些值:

import  doSomething  from './helper';

@Component(
    ...
)
export class AppComponent 
    test() 
        const data = doSomething(1);
        return data.something ? 1: 2;
    

doSomething 只是一个简单的辅助函数:

export function doSomething() 
    return  something: 1 ;

是否可以在单元测试中模拟或监视此函数(以便我可以控制其返回值)?还是我必须更改组件中的方法?

请注意:doSomething() 可以是 lodash 函数、常量、类等。我只是尽量让示例保持简单。


我尝试过的事情:

SpyOn 不起作用,因为函数未附加到任何东西

将模拟函数导入TestBed.configureTestingModuleimports 数组会得到Unexpected value 'doSomething' imported by the module 'DynamicTestModule'. Please add a @NgModule annotation.

为其创建服务是可行的,但必须为每个导入的函数创建服务感觉很愚蠢

【问题讨论】:

请问你为什么要模拟它?您还提到了SpyOn,这意味着间谍而不是嘲笑。 我希望能够控制函数的返回值,所以我不必关心这个函数中的逻辑,因为它应该有一个单独的单元测试。也许嘲笑是错误的词。只要我可以控制单元测试中的返回值,间谍也会很好 你可以试试 spyOn(service, 'function').and.returnValue('your value here') 我同意,但这实际上不会为嘲笑/间谍活动提供更有力的理由吗?我希望插入 y 时返回值 x,插入 B 时返回 A。如果这个函数需要两个都需要参数的类怎么办。看起来工作量很大,而且容易出错。 这就是为什么模拟/间谍是完美的。因为在测试期间我确实不关心内部结构。我只是想涵盖可能的结果,以便我可以正确地对我的功能进行单元测试。让我们扭转局面。你为什么不模拟/窥探某些东西? 【参考方案1】:

无法模拟外部函数,但您可以执行以下操作,效果很好。

import  doSomething  from './helper';

@Component(
    ...
)
export class AppComponent 
    const doSomethingRef = doSomething; 
    test() 
        const data = this.doSomethingRef(1);
        return data.something ? 1: 2;
    

现在,因为我们可以模拟 doSomethingRef

describe('AppComponent ', () => 
  let appComponent: AppComponent ;
  beforeEach(() => 
    TestBed.configureTestingModule();
    appComponent= TestBed.inject(AppComponent);
  );

  it('should allow mocking', () => 
    (appComponent as AppComponent).doSomethingRef = jasmine.createSpy('doSomethingRef ').and.returnValue(1);
    expect(guard.test()).toEqual(1);
  );
 

【讨论】:

【参考方案2】:

在您的规范文件中以这种方式导入帮助程序:

import * as helper from './helper';

并且在您的 it() 中,您可以监视助手对象并返回请求的值:

spyOn(helper, 'doSomething').and.returnValue();

【讨论】:

尝试此操作时,我收到以下错误:错误::doSomething 未声明可写或没有设置器 A​​ngular 7 (CLI) 相同。 @rryter 你找到解决方案了吗? 恐怕还没有。 @PeterI 我在另一个帖子中发布了解决方案:***.com/a/54757283/1387126 来自同一个问题,但不同的案例 - 这是我的案例 - 以及不同的解决方案(通过 tsconfig):github.com/jasmine/jasmine/issues/1414#issuecomment-501209914

以上是关于如何在 Angular 单元测试中模拟/监视导入的函数的主要内容,如果未能解决你的问题,请参考以下文章

Angular 6 - 如何在单元测试中模拟 router.events url 响应

在单元测试中使用参数模拟 ngrx 存储选择器(Angular)

在 AngularJS 单元测试中模拟模块依赖

Angular 2:如何在单元测试时模拟 ChangeDetectorRef

在AngularJS单元测试中模拟模块依赖性

Angular 2 单元测试组件,模拟 ContentChildren