簡體   English   中英

模擬對象如何在Angular jasmine單元測試中工作

[英]How mock object work in Angular jasmine unit test

我正在學習單元測試和Angular,所以我兩個都是初學者。 我已經提到了幾個關於單元測試http的角度的教程和文章。

我無法理解httpMock使用HttpTestingController做了什么。 我們稱實際服務的功能然后我們稱之為模擬? 什么是潛在的過程? 請參閱一些文章以獲得更好的理解。

提前致謝。

編輯:這是我堅持使用httpMock的問題

我們以我的一個文件為例,好嗎?

import { SimpleConfiguration } from '../../../../../model/SimpleConfiguration';
import { SessionService } from '../../../session/session.service';
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ConfigurationService } from './configuration.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

describe('ConfigurationService', () => {

  let httpMock: HttpTestingController;
  let service: ConfigurationService;

  const createFakeFile = (fileName: string = 'fileName'): File => {
    const blob = new Blob([''], { type: 'text/html' });
    blob['lastModifiedDate'] = '';
    blob['name'] = fileName;
    return <File>blob;
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        HttpClientTestingModule
      ],
      providers: [ConfigurationService, SessionService]
    });

    httpMock = TestBed.get(HttpTestingController);
    service = TestBed.get(ConfigurationService);
  });

  it('should be created', done => {
    expect(service).toBeTruthy();
    done();
  });

  it('getConfigurations should GET on postes-sources/:postID/configuration', (done) => {
    service.getConfigurations(0).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/configurations');
    expect(successRequest.request.method).toEqual('GET');
    successRequest.flush(null);
    httpMock.verify();
  });

  it('uploadFile should POST on postes-sources/:postID/configuration', (done) => {
    service.uploadFile(0, createFakeFile(), new SimpleConfiguration()).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/configurations');
    expect(successRequest.request.method).toEqual('POST');
    successRequest.flush(null);
    httpMock.verify();
  });

  it('updateComment should POST on postes-sources/:postID/configurations/:confID', (done) => {
    service.updateConfiguration(0, 0, new SimpleConfiguration()).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/configurations/0');
    expect(successRequest.request.method).toEqual('POST');
    successRequest.flush(null);
    httpMock.verify();
  });

  it('getComponentInformations should GET on postes-sources/:postID/tranches/:trancheID/parametres', (done) => {
    service.getComponentInformations(0, 0).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/tranches/0/parametres');
    expect(successRequest.request.method).toEqual('GET');
    successRequest.flush(null);
    httpMock.verify();
  });
});

讓我一步一步向你詳細解釋。

  1. 我們首先describe我們的測試。 它允許我們對測試進行分組。 在這種情況下,我們按功能對測試進行分組,我們的功能是名為ConfigurationService的服務。 然后我們提供一個回調函數:這是Jasmine運行測試的函數。

  2. 接下來,我們聲明我們的變量。 在這里,我們聲明了2個變量和一個函數: httpMockservicecreateFakeFile() 這些變量在整個測試組中都會有所幫助,因此我們將它們聲明為頂級。

  3. 然后是beforeEach :在每次測試之前,這個函數都會運行,做一些事情。 在這一步中 ,它將創建一個TestBed :這是一些樣板代碼,它將創建某種Angular模塊,以允許您的測試運行,就像您的功能在真正的Angular應用程序中一樣。

在這個測試床中,您需要聲明您的依賴項 :因為我正在測試HTTP服務,所以我必須導入HTTP測試模塊,並且因為我的測試使用路由,所以我還必須導入路由器測試模塊。 我也需要導入正在測試的服務,並導入一個SessionService因為我也在我的服務中使用它。

之后,我通過TestBed.get 獲取這些依賴項的服務實例 :這將允許我監視它們的屬性,並查看它們的值以及它們是否被調用。 這也允許我調用我想測試的函數。

  1. 有第一次測試。 第一個非常簡單,默認情況下實現:我測試服務是否正確創建。 如果沒有,這意味着你缺乏依賴,或者你嘲笑你的依賴錯誤。 expect(service).toBeTruthy()是真正的測試: 對於expect,jasmine期望 (duh) 服務是truhty (即它不應該等於undefined或null)。

  2. 下一個測試是一個真正的測試:在這個測試期間,我希望我的函數用某個動詞調用某個端點。

我首先說,一旦打電話,我必須結束測試。 這是通過調用done ,這是上面給出的回調。

然后,我模擬了一個HTTP調用:這意味着我讓Angular相信我正在進行HTTP調用,但實際上我假裝。 但在它看來,它就像是在制造一個真實的:這就是模擬: 模擬行為或價值 如您所見,我在特定端點上模擬HTTP調用,並且我期望一個特定的HTTP謂詞。

最后,如果我的函數getConfigurations GETS在該URL上,我的測試將成功,如果沒有,它將失敗。 這意味着如果我在實際服務中更改了端點,則測試將失敗:此測試可防止出現副作用

其他測試也是如此,所以我猜我不需要解釋它們。

如果你想知道,我沒有單獨做,就像你請求幫助並遵循教程一樣。 但是一旦你習慣它,它就會變得非常快速和容易地測試你的功能。

我希望這會有所幫助,隨時可以問你想要我解釋的任何事情!

模擬服務的想法是你不需要使用實際的功能 (真正的http調用),但你需要服務方法來運行你的代碼,沒有任何例外。

例如:您有一個組件,在某些時候通過Http從某些API收集數據。 其中一個單元測試應該測試你的組件是否進行了這個調用,但如果那里有一個真正的調用你就不會給出該死的。 單元測試的重點是測試呼叫是否已經發生。

編輯:如果某些內部邏輯進行調用以收集數據以顯示某些內容,則會發生同樣的情況。 你應該模擬http調用並返回你自己的數據。 你的單元測試不應該與外界有關。 想象一下,您的測試將在沒有互聯網的環境中運行。 測試應該隨時通過。

無論您測試的是哪種服務,此方案都適用。 單元測試應該具有單一的責任感。 他們不應該依賴於與他們的主要目的不同的東西。

我實際上剛剛在過去的一周遇到過這個問題,所以這在我的腦海中非常新鮮。 Jasmine對我有點困惑,所以我可以分享我為解決問題所做的工作。

首先,Angular教程會誤導新測試人員。 它聲稱我們應該使用Jasmine,但后來開始使用TestBed,這有點誤導。 我最終選擇了TestBed,我可以告訴你我用過的東西。

所以你有你的描述:

descripe('randomService', () -> {

}

你需要初始化你的`randomService':

descripe('randomService', () -> {
    let randomService: RandomService;         
}

使用beforeEach(),你可以在每個前重新初始化,賦值等, it在你的描述語句。

descripe('randomService', () -> {
   let randomService: RandomService;         
   beforeEach(() => {
       imports: [
           HttpClientTestingModule
       ]
   });
}

所以我告訴角度來重新導入HttpClientTestingModule各之前it塊。 我的randomService需要HttpClient所以我需要創建一個Jasmine Spy對象,它返回我告訴它的內容,而不是讓我的randomService命中實際的后端並改變后端的實際數據。

descripe('randomService', () -> {
   let randomService: RandomService;
   httpClientSpy;

   beforeEach(() => {
       imports: [
           HttpClientTestingModule
       ]
   });
   httpClientSpy = jasmine.CreateSpyObj('Http', ['get']);
   randomService = new RandomService(<any> httpclientSpy);       
}

所以現在每當我在randomService中使用'get'方法時,它真的會使用httpClientSpy,並且它編譯因為我告訴randomService我的參數類型為'any'並且它的'最佳知識,實際上是真正的HttpClient即使它不是。 要正確使用此功能,您必須為假冒產品設置假回報:

descripe('randomService', () -> {
   let randomService: RandomService;
   httpClientSpy;
   mockResponse = { 1: ['first', 'second', 'third'] };
   beforeEach(() => {
       imports: [
           HttpClientTestingModule
       ]
   });
   httpClientSpy = jasmine.CreateSpyObj('Http', ['get']);
   randomService = new RandomService(<any> httpclientSpy);       
});

    it('should return first, second, third', () => {
        spyOn(httpClientSpy, 'get').and.returnValue(Observable.of(mockResponse));
        // randomService. <your get method here...>
        randomService.getValue().subscribe((response) =>
            expect(resposne[0].length).toEqual(3);
};
});

那個響應應該是在我們的beforeEach()創建的beforeEach()它不必在beforeEach()中,但是在這個例子中我把它放在那里。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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