如何在 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.configureTestingModule
的imports
数组会得到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();
【讨论】:
尝试此操作时,我收到以下错误:错误:以上是关于如何在 Angular 单元测试中模拟/监视导入的函数的主要内容,如果未能解决你的问题,请参考以下文章
Angular 6 - 如何在单元测试中模拟 router.events url 响应
在单元测试中使用参数模拟 ngrx 存储选择器(Angular)