簡體   English   中英

使用Jasmine / karma進行Angular 4單元測試以及http發布模擬-如何修復

[英]Angular 4 unit testing with jasmine /karma with http post mocking - how to fix

我有一個服務,我想在角度4打字稿茉莉中進行單元測試。

現在, http正在post ,它返回一個標識,但是..它沒有發送任何內容。

我只想擁有良好的代碼覆蓋率,但我不明白如何完全完成此模擬語句。

這是我的服務文件中http發布的方法

addSession() {
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });

        return this.http.post(this.url, JSON.stringify({}), options)
            .map((response: Response) => response.json());

}

然后是SPEC FILE ,我沒有真正測試的東西,我想是冒充我從服務http帖子收到了一個數字,響應應該是000000014

規格

import { TrackerFormService } from './tracker-form.service'
import { Observable } from 'rxjs/Observable'

describe('TrackerFormService', () => {

    let trackerFormService: TrackerFormService,
        mockHttp;

    beforeEach(() => {
        mockHttp = jasmine.createSpyObj('mockHttp', ['get', 'post', 'put']
        )
        trackerFormService = new TrackerFormService(mockHttp);
    });

    describe('addSession', () => {

        it('add session ', () => {
              // how to test,  what to test?    
              // response , is a number?  how to mock/fake this?

        })

    })

})

為了實現所需的功能,所需的模擬程序是一個簡單的函數,該函數返回的結果與POST正常執行的結果相同; 另一件事是您的測試不應真正在服務器上運行,因此您將需要以下內容(您可能需要添加其他依賴項):

import { HttpModule } from '@angular/http';
import { TrackerFormService } from './tracker-form.service'
import { Observable } from 'rxjs/Observable'

describe('TrackerFormService', () => {
// Mock the service like this and add all the functions you have in this fashion
let trackerFormService: TrackerFormService,
  mockService = {
    addSession: jasmine.createSpy('addSession').and.returnValue(Observable.of('your session object mock goes here'))
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpModule],
      providers: [{
        provide: TrackerFormService,
        useValue: mockService
      }]
    });
  });

  // Do this trick to inject the service every time, and just use `service` in your tests
  beforeEach(inject([TrackerFormService], (trackerFormService) => {
    service = trackerFormService;
  }));

  describe('addSession', () => {
    it('add session ', () => {
      let fakeResponse = null;

      // Call the service function and subscribe to it to catch the fake response coming from the mock.
      service.addSession().subscribe((value) => {
        // in here value will be whatever you put as returnValue (remember to keep the observable.of())
        fakeResponse = value;
      });

      // expects as in any test.
      expect(fakeResponse).toBeDefined();
      expect(fakeResponse).toBe('your session object mock goes here');
    });
  });
});

Angular 4.3附帶了HttpClient服務,該服務取代了Http,並提供了一種簡單的模擬HTTP請求的方法。 在官方頁面上有很好的記錄: https//angular.io/guide/http

很好,您可以通過設置測試/模擬的方式來偽造郵寄回郵,並檢查是否獲得了預期的結果。 通過這樣做,您將測試map語句將正確轉換模擬的響應。 通過您的間諜,您還可以檢查post方法的調用方式。 這將檢查選項是否符合您的期望。

但是我認為這是一個相當復雜的解決方案。 我寧願通過拆分方法來避免模擬和間諜,因此每種方法都只是做一件事。 因為您的addSession方法當前正在執行三種不同的操作(但在邏輯上是依賴的):

  1. 為addSession xhr調用創建選項
  2. 執行通話
  3. 轉換響應

如果將方法分成三部分,則可以在單獨的測試中輕松測試方法1和方法3,方法2僅包含對http庫的調用。 這樣,您無需調用http庫即可獲得與上述相同的測試值。

現在關於方法2呢...它仍然未經測試,我認為根本沒有理由對其進行測試。 因為您沒有編寫該代碼。 另外,如果您使用的是angulars http模塊,那么我可以確定它們本身具有可靠的單元測試。

您的服務的響應應該已經包含在附加的集成測試中,以較少的頻率運行,檢查服務api仍會返回您期望的結果。

如果您確實希望代碼覆蓋范圍內的一行為綠色,則可以選擇使用一個名為nock的庫。 Nock會攔截您的應用程序引起的所有xhr流量。 在您的測試文件中,您可以將xhr請求映射到帶有nock對象的模擬響應。

 var scope = nock('http://myapp.iriscouch.com') .post('/users', { username: 'pgte', email: 'pedro.teixeira@gmail.com' }) .reply(201, { ok: true, id: '123ABC', rev: '946B7D1C' }); 

復制自: https : //www.npmjs.com/package/nock

有關一般測試以及要測試多少的參考​​和其他信息,我建議觀看Justin Searls的“預算現實”

HTTP服務請求的示例測試用例

 describe('Forgot Password Controller', function () { var $controller, $httpBackend, $q, $rootScope, $state, controller, scope, accountProvider; beforeEach(module('app')); beforeEach(inject(function (_$injector_, _$controller_, _$rootScope_) { $controller = _$controller_; $rootScope = _$rootScope_; $httpBackend = _$injector_.get('$httpBackend'); $state = _$injector_.get('$state'); $q = _$injector_.get('$q'); accountProvider = _$injector_.get('accountProvider'); scope = _$rootScope_.$new(); controller = $controller(app.controllers.forgotPassword, { $state: $state, accountProvider: accountProvider }); })); afterEach(function () { $httpBackend.verifyNoOutstandingRequest(); $httpBackend.verifyNoOutstandingExpectation(); }); describe('forgot password submission', function () { it('Can submit a forgot password request successfully', function () { $httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(200); spyOn($state, 'go'); controller.form = { emailAddress: 'aks@gmail.com' }; controller.submit(); expect(controller.submitting).toBe(true); $httpBackend.flush(); expect(controller.submitting).toBe(false); expect($state.go).toHaveBeenCalledWith('login', { successMessage: 'An email sent to ' + controller.form.emailAddress + ' contains instructions for resetting your password.' }); }); it('Can handle when a user is not found when submitting a forgot password request', function () { $httpBackend.expectPOST(app.env.EDGE_SERVICE_PATH + '/events/requestPasswordReset').respond(404); spyOn($state, 'go'); controller.form = { emailAddress: 'aks@gmail.com' }; controller.submit(); expect(controller.submitting).toBe(true); $httpBackend.flush(); // We intentionally want to make it appear to the user that the password reset email was sent even when a user // does not exist, to help hide info about which users exist in the system expect(controller.submitting).toBe(false); expect($state.go).toHaveBeenCalledWith('login', { successMessage: 'An email sent to ' + controller.form.emailAddress + ' contains instructions for resetting your password.' }); }); it('Can handle unexpected errors from submitting a forgot password request', function () { $httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(500); controller.submit(); $httpBackend.flush(); expect(controller.errors.unexpectedError).toBe(true); }); it('Can handle 422 validation errors from submitting a forgot password request', function () { var responseData = { fieldErrors: { username: [{code: 'error'}, {code: 'required', message: 'This is required.'}] } }; $httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(422, responseData); controller.submit(); $httpBackend.flush(); expect(controller.errors.validationErrors).toBe(true); expect(controller.errors.fieldErrors).toEqual(responseData.fieldErrors); }); it('Can handle 503 service unavailable from submitting a forgot password request', function () { $httpBackend.expectPOST("URL DOMAIN" + '/events/requestPasswordReset').respond(503); controller.submit(); $httpBackend.flush(); expect(controller.errors.serviceUnavailable).toBe(true); }); }); }); 

暫無
暫無

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

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