![](/img/trans.png)
[英]Angular testing: Is it possible to stub service provided by imported module
[英]How to stub imported module without methods in Angular?
我有一個帶有 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()
的功能。
spyOn
上jwtDecode
當我使用spyOn
,我需要一個帶有方法的對象。 所以對於導入的jwtDecode
這將不起作用,因為它本身就是一個函數:
spyOn(jwtDecode, '<method?>').and.callFake(() => 'fake-token');
callFake
上getTokenPayload
我試過使用:
spyOn(service, 'getTokenPayload').and.callFake(() => 'fake-token');
...這可以防止發生任何錯誤。 但是,我的代碼覆蓋率報告現在顯示函數getTokenPayload
沒有被覆蓋。 此外,我在使用外部 NPM 模塊的應用程序中有其他功能,我不想忽略代碼覆蓋率,因為它們可能在應該測試的方法內部有其他實現。
createSpy
上jwtDecode
我嘗試覆蓋導入的jwtDecode
並創建一個間諜:
const jwtDecode = jasmine.createSpy('jwtDecode').and.returnValue('fake-token');
這給了我與上面相同的錯誤,表明jwtDecode
在我的實際AuthService
服務中沒有被覆蓋。
window
作為對象從這個問題我讀到全局模塊可能附加到window
對象。 因此,我嘗試對jwt-decode
做同樣的事情:
測試里面...
console.log(window.jwtDecode); // undefined
console.log(window.jwt_decode); // undefined
不幸的是,這兩個值undefined
在window
對象上undefined
。
我想一般來說問題變成了:
如何存根導入的 NPM 模塊? 特別是,如果它們不是對象而是函數(沒有在 Jasmine spyOn
使用的方法),如何存根它們?
你非常接近! 由於服務只是一個類,因此測試它的最佳方法是實例化一個新的並監視它,就像您正在做的那樣。 如果您想監視導入的方法,則需要以某種方式將其包含在您的服務中。 否則,您的測試將無法知道該方法是什么。
所以在你的服務上有一個屬性:
jwtDecode = jwtDecode; // the imported one
並呼吁它作為this.jwtDecode
在getTokenPayload
方法。
然后以下將起作用:
const service = new AuthService( /* constructor args */ );
const jwtDecode = spyOn(service, 'jwtDecode');
jwtDecode.and.returnValue('fake-token');
只需監視jwt-decode
模塊的default
導出,即jwtDecode
函數。 這樣就不必按照建議污染您的服務。
例如,在您的規范文件中:
import * as jwt from 'jwt-decode';
...
// return whatever data structure you require
spyOn(jwt, 'default').and.returnValue({ someData: ['x', 'y', 'z'] });
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.