【发布时间】:2018-07-06 19:35:27
【问题描述】:
我有一个带有 Jasmine 测试框架的 Angular 应用程序。该应用程序有一个名为 AuthService 的服务,用于处理 JSON Web 令牌的解码:
auth.service.ts
import * as jwtDecode from 'jwt-decode';
...
@Injectable()
export class AuthService {
...
public getTokenPayload(token) {
return jwtDecode(token);
}
}
现在我想存根模块 jwtDecode 并在测试时返回一个假值:
auth.service.spec.ts
...
it('should get a token payload', () => {
const fakeToken = 'fake-token';
spyOn(service, 'getTokenPayload').and.callThrough();
const tokenPayload = service.getTokenPayload(fakeToken);
expect(tokenPayload).toBe('fake-token');
});
因为 'fake-token' 不是有效的 JSON Web 令牌,我的测试失败并显示以下消息:
InvalidTokenError: Invalid token specified: undefined is not an object (evaluating 'str.replace')
这可能是jwt-decode 模块产生的错误,这是预期的。我不想仅仅为了测试目的而包含另一个模块来创建有效的 JSON Web 令牌。相反,我想存根 jwtDecode() 的功能。
我尝试过的
1。在jwtDecode 上使用spyOn
当我使用spyOn 时,我需要一个带有方法的对象。所以对于导入的jwtDecode 这将不起作用,因为它本身就是一个函数:
spyOn(jwtDecode, '<method?>').and.callFake(() => 'fake-token');
2。在getTokenPayload 上使用callFake
我尝试过使用:
spyOn(service, 'getTokenPayload').and.callFake(() => 'fake-token');
...这样可以防止发生任何错误。但是,我的代码覆盖率报告现在显示函数 getTokenPayload 没有被覆盖。此外,我在应用程序中还有其他使用外部 NPM 模块的功能,我不想忽略代码覆盖率,因为它们可能在应该测试的方法内有其他实现。
3。在jwtDecode 上使用createSpy
我尝试覆盖导入的jwtDecode 并创建一个间谍:
const jwtDecode = jasmine.createSpy('jwtDecode').and.returnValue('fake-token');
这给了我与上面相同的错误,表明jwtDecode 没有在我的实际AuthService 服务中被覆盖。
4。使用window 作为对象
从this question 我读到全局模块可能附加到window 对象。因此,我尝试为jwt-decode 做同样的事情:
测试内...
console.log(window.jwtDecode); // undefined
console.log(window.jwt_decode); // undefined
不幸的是,window 对象上的两个值都是 undefined。
问题
我想一般来说问题变成了:
如何存根导入的 NPM 模块?特别是,如果它们不是对象而是函数(没有在 Jasmine spyOn 中使用的方法),如何存根它们?
【问题讨论】:
-
我认为你可以监视 window.jwtDecode。看看stackoverflow.com/questions/9510148/…
-
感谢您的回答。不幸的是,我早些时候遇到了这种方法,但没有运气。我已经更新了这个问题,提供了我在这种方法中的发现。
标签: angular unit-testing typescript jasmine karma-jasmine