2017-09-26 3 views
5

각도 4 타이프 스크립트 재스민에서 단위 테스트를 원합니다.http post mocking으로 jasmine/karma로 각도 4 단위 테스트 - 수정 방법

이제 httppost을 수행하고 있지만 ID를 반환하지만 아무 것도 보내지 않습니다.

나는 단지 좋은 코드 커버리지를 원하지만 나는이 조롱 진술을 어떻게 완성하는지 이해하지 못한다. 여기

내가 정말 테스트, 내가 번호를받은 날조 가정 해 봅시다 무엇을하지 않는, 내 서비스 파일

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 파일에서 HTTP 게시하는 방법입니다 다시 서비스 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? 

     }) 

    }) 

}) 

답변

2

를 요청, 당신이 필요로하는 모의은 간단한 기능입니다 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'); 
    }); 
    }); 
}); 
0

Angular 4.3에는 Http를 대체하고 HTTP 요청을 모의하는 더 쉬운 방법을 제공하는 HttpClient 서비스가 있습니다. 그것은 잘 공식 페이지에 문서화 : HTTP 서비스에 대한 https://angular.io/guide/http

+0

저스틴 Searls에 의해 일반적으로 테스트 및 얼마나 많은 테스트하는 내가 "예산의 현실"을보고 추천에 대한 참조 및 자세한 내용은 https://www.npmjs.com/package/nock

전 이미 다른 것을 사용하고 있는데, 나는 내가 갖고있는 것을 조롱하는 법을 묻고있었습니다. 당신이 말하는 것은 닷넷 코어, 또는 C# 7에 상응하는 것입니다. 이제 XYZ를 할 수 있습니다. 너무 멋지거나 2. ES6에서 이제는 훨씬 더 좋습니다 ... –

+0

내가 제대로 이해한다면 TrackerFormService.addSession() 메서드를 내 모토에서 이해할 수없는 TrackerFormService 테스트에서 모의하지 않고 실제 구현을 테스트하려고하기 때문에 조롱하고 싶습니다. – TekTimmy

+0

응답에서 000000015와 같은 숫자를 반환하므로 사람들이 HTTP 게시 서비스 프로세스를 조롱하거나 위조 한 것 같습니다. 나는 예제를 찾을 수 있지만, 특정 테스트를 모방하거나 위조하는 방법을 알아 내려고 시도하는 것이 너무 구체적입니다. 나는 그것을하는 방법을 알고 있다고 주장하지 않는다. 그래서 질문을하고있다. –

0

샘플 테스트 케이스 당신이 원하는 것을 달성하기 위해

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: '[email protected]' }; 
 

 
      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: '[email protected]' }; 
 

 
      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); 
 
     }); 
 

 
    }); 
 

 
});

+4

이것은 각도 4 해결책이 아니다. –

+0

예, 여기 나머지 apis에 대한 테스트 케이스를 작성하는 방법에 대한 아이디어를 제공합니다. – AnilKumar

+0

이것이 서비스를 조롱하는 데 어떻게 도움이 될까요 ?? –

0

길을/당신에게 가짜 수 조롱 통화 후 반환 및 예상 결과를 확인하십시오. 이렇게하면 조롱 된 응답이 맵 문에 의해 올바르게 변환되는지 테스트하게됩니다. 스파이를 사용하면 post 메소드가 호출 된 방법을 확인할 수도 있습니다. 옵션이 예상 한 것과 일치하는지 확인합니다.

제 의견으로는 다소 복잡한 해결책입니다. 나는 방법을 나누어서 모든 방법이 다만 1 개의 것을하고있다 mock와 간첩을 피하는 것을 선호 할 것입니다. 당신의 addSession 방법은 현재 세 가지 (아무런 논리적으로 따라 다름) 일하기 때문에 : 전화를

  1. 는 addSession의 XHR 호출
  2. 에 대한 옵션을 생성을 수행
  3. 는 응답

당신이 침입하는 경우를 변환 세 가지 방법을 사용하면 별도의 테스트에서 # 1과 # 3 메소드를 쉽게 테스트 할 수 있으며 # 2 메소드는 http 라이브러리 호출 만 포함합니다. 이렇게하면 http 라이브러리를 호출하지 않고도 위와 동일한 테스트 값을 얻을 수 있습니다.

이제는 방법 2에 대해 ... 아직 테스트되지 않았으며 제 의견으로는 전혀 테스트 할 이유가 없습니다. 왜냐하면 당신은 그 코드를 작성하지 않았기 때문입니다.또한 각도 http 모듈을 사용하고 있다면 나는 그들이 단단한 단위 테스트 자체를 가지고 있다고 확신합니다.

귀하의 서비스에 대한 응답은 이미 추가 통합 테스트에 포함되어야합니다. 자주 실행하지 않으면 서비스 API가 예상 한 결과를 반환합니다.

코드 커버리지에서 한 줄을 녹색으로 표시하려면 nock이라는 라이브러리를 선택적으로 사용할 수 있습니다. Nock은 앱에서 발생하는 모든 xhr 트래픽을 차단합니다. 테스트 파일에서 nock 객체로 xhr 요청을 조롱 된 응답에 매핑 할 수 있습니다.

var scope = nock('http://myapp.iriscouch.com') 
 
       .post('/users', { 
 
        username: 'pgte', 
 
        email: '[email protected]' 
 
       }) 
 
       .reply(201, { 
 
        ok: true, 
 
        id: '123ABC', 
 
        rev: '946B7D1C' 
 
       });
은 기술 :