Служба тестирования угловая - PullRequest
1 голос
/ 25 апреля 2019

Я столкнулся с проблемой, я не имею ни малейшего понятия, как ее решить, потому что я так задираюсь с тестированием впереди.

Сейчас я тестирую сервис с таким кодом:

import { Injectable } from '@angular/core';
import { EndpointLocatorService } from './endpointLocator.service';
import { Http, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class CancelAppService {

    constructor(private readonly http: Http,
        private readonly _endPointLocator: EndpointLocatorService) { }

    getScopeSignature(signatureToken: string) {
        const url = this._endPointLocator.locate('cancelApp');
        const language = sessionStorage.getItem('languageSession');
        const headers = new Headers({
            'Content-Type': 'application/json',
            'Accept-Language': language,
            'X-B3-TraceId': sessionStorage.getItem('requestID')
        });
        const body = JSON.stringify({ 'signatureToken': signatureToken });
        return this.http.post(url, body, { headers }).map(data => {
            return data.json();
        }).catch((error: any) => {
            return Observable.throw(new Error(error.status));
        });
    }
}

Файл тестирования содержит это:

import { TestBed } from '@angular/core/testing';
import { CancelAppService } from './cancelApp.service';
import { HttpModule } from '@angular/http';
import { EndpointLocatorService } from './endpointLocator.service';
import { AppConfig } from '../app.config';
import 'jasmine';

fdescribe('CancelAppService', () => {
    let cancelService: CancelAppService; // Add this
    let endLocator: EndpointLocatorService;
    const mockData = {
        "signature_token": "returnedToken"
    };
    const body = JSON.stringify({ 'signatureToken': 'givenToken' });
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [
                HttpModule
            ],
            providers: [
                CancelAppService,
                AppConfig,
                EndpointLocatorService
            ]
        });
        cancelService = TestBed.get(CancelAppService); // Add this
        endLocator = TestBed.get(EndpointLocatorService);
    });

    it('should be created', () => { // Remove inject()
        expect(cancelService).toBeDefined();
    });

    it('should call the service', () => {
        spyOn(endLocator, 'locate').and.returnValue('someUrl');
        spyOn(cancelService, 'getScopeSignature').and.callThrough();
        cancelService.getScopeSignature(body);
        expect(cancelService.getScopeSignature).toHaveBeenCalled();
    });

    it('should return a object', () => {
        (done: DoneFn) => {
            spyOn(endLocator, 'locate').and.returnValue('someUrl');
            spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
            cancelService.getScopeSignature(body).subscribe(data => {
                expect(data).toEqual(mockData);
                done();
            });
        }
    });
});

Проблема в том, что, когда я пытаюсь протестировать возвращенную карту данных, я выгляжу как тест на успешность, но покрытие говорит, что я не охватил линии карты, и ловлю.

enter image description here

Есть идеи, что я делаю не так? и как это решить?

Спасибо большое !!

1 Ответ

0 голосов
/ 25 апреля 2019

Вы издеваетесь над тестируемой службой, вам следует высмеять службу, используемую вашей службой EndpointLocatorService и, возможно, даже HttpClient, чтобы минимизировать насмешки. Вы можете проверить это, пройдя по коду.

Позвольте мне объяснить в коде, почему эти строки не удаляются.

// In this example, the lines are hit, but after the test exited.
it('should call the service', () => {
    spyOn(endLocator, 'locate').and.returnValue('someUrl');
    spyOn(cancelService, 'getScopeSignature').and.callThrough();
    // Here you are calling a method yourself and checking that it was
    // called, it doesn't make sense, this test should make sure
    // You should check that your endLocator was called.
    // Note that because you are not waiting for the promise to resolve,
    // The test finishes before either callback is handled.
    cancelService.getScopeSignature(body);
    expect(cancelService.getScopeSignature).toHaveBeenCalled();
});


// In this example the lines in your test are never hit because you
// mocked it
it('should return a object', () => {
    (done: DoneFn) => {
        spyOn(endLocator, 'locate').and.returnValue('someUrl');
        // Here you are mocking getScopeSignature completely so it doesn't
        // Run any of your lines that you are trying to test
        // It just tests that you mocked it correctly
        spyOn(cancelService, 'getScopeSignature').and.returnValue(mockData);
        cancelService.getScopeSignature(body).subscribe(data => {
            expect(data).toEqual(mockData);
            done();
        });
    }
});

Я не могу переписать ваш тест, так что он на самом деле тестирует его, потому что это зависит от того, как работает EndpointLocatorService, и вы можете также выбрать его на этом уровне. Обычно я выбираю макет на уровне HttpClient, поскольку могу копировать ответы вставки со вкладки сети.

Суть в том, что вам нужно имитировать сервисы, используемые вашим сервисом, а не сам сервис. У вас есть возможность издеваться над прямыми услугами, используемыми вашим компонентом, или вы можете издеваться на более глубоком уровне. Например, вашему EndpointLocatorService может потребоваться позвонить по номеру HttpClient, и вы можете выбрать макет любой из этих услуг.

См. https://angular.io/guide/testing#httpclienttestingmodule и https://alligator.io/angular/testing-httpclient/

...