簡體   English   中英

如何在 Angular 中沒有方法的情況下存根導入的模塊?

[英]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()的功能。

我試過的

1.使用spyOnjwtDecode

當我使用spyOn ,我需要一個帶有方法的對象。 所以對於導入的jwtDecode這將不起作用,因為它本身就是一個函數:

spyOn(jwtDecode, '<method?>').and.callFake(() => 'fake-token');

2.使用callFakegetTokenPayload

我試過使用:

spyOn(service, 'getTokenPayload').and.callFake(() => 'fake-token');

...這可以防止發生任何錯誤。 但是,我的代碼覆蓋率報告現在顯示函數getTokenPayload沒有被覆蓋。 此外,我在使用外部 NPM 模塊的應用程序中有其他功能,我不想忽略代碼覆蓋率,因為它們可能在應該測試的方法內部有其他實現。

3.使用createSpyjwtDecode

我嘗試覆蓋導入的jwtDecode並創建一個間諜:

const jwtDecode = jasmine.createSpy('jwtDecode').and.returnValue('fake-token');

這給了我與上面相同的錯誤,表明jwtDecode在我的實際AuthService服務中沒有被覆蓋。

4. 使用window作為對象

這個問題我讀到全局模塊可能附加到window對象。 因此,我嘗試對jwt-decode做同樣的事情:

測試里面...

console.log(window.jwtDecode); // undefined
console.log(window.jwt_decode); // undefined

不幸的是,這兩個值undefinedwindow對象上undefined

問題

我想一般來說問題變成了:

如何存根導入的 NPM 模塊? 特別是,如果它們不是對象而是函數(沒有在 Jasmine spyOn使用的方法),如何存根它們?

你非常接近! 由於服務只是一個類,因此測試它的最佳方法是實例化一個新的並監視它,就像您正在做的那樣。 如果您想監視導入的方法,則需要以某種方式將其包含在您的服務中。 否則,您的測試將無法知道該方法是什么。

所以在你的服務上有一個屬性:

jwtDecode = jwtDecode; // the imported one

並呼吁它作為this.jwtDecodegetTokenPayload方法。

然后以下將起作用:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM