TypeError: Невозможно прочитать свойство 'fetchData' неопределенной кармы jasmine - PullRequest
0 голосов
/ 02 ноября 2018

это мой первый модульный тест в угловых 7, я хочу проверить мой метод в моей службе, этот метод возврата Наблюдаемый :

fetchData(chronoInfo: ALChrono): Observable<any> {
        // construct API parameters and URL
        var URL: string = this.urlDecoratorService.urlAPIDecorate("AL", "GetAccessChrono");

        var params = this.urlDecoratorService.generateParameters({
            year: chronoInfo.year,//Année
            month: chronoInfo.month,//Mois (peut être null)
            sortBy: chronoInfo.sortBy,// Champ de tri
            sortDirection: chronoInfo.sortDirection,//True pour inverser l'ordre de tri
            pageNumber: chronoInfo.currentPage,//Page de résultats
            pageSize: chronoInfo.pageSize//Nb enregistrements par page
        });

        return this.apiFetcher.fetchJson(URL, params);
        //retourne les AL par année & mois
    }

и тест этого метода:

import { TestBed, async, inject } from '@angular/core/testing';
import { AnnonceChronoDetailService } from './annonce-chrono-detail.service';
import { HttpClientModule } from '@angular/common/http';
import { UrlDecoratorService } from "src/app/common/url-decorator.service";
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { APIFetcherService } from "src/app/services/common/api-fetcher.service";
import { Http, ConnectionBackend, RequestOptions, HttpModule } from "@angular/http";
import { ALChrono } from '../../common/IALChrono.interface';
import { Observable } from 'rxjs';

describe('AnnonceChronoDetailService', () => {
    let service: AnnonceChronoDetailService;
    let alChrono: ALChrono = { //it's an interface'
        year: 2012,
        month: -1,
        sortBy: 'asc',
        sortDirection: true,
        currentPage: 1,
        pageSize: 15
    }

    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpModule],
            providers: [
                AnnonceChronoDetailService,
                UrlDecoratorService,
                APIFetcherService,
                Http,
                ConnectionBackend]
        });
    });


    it('should be created', inject([AnnonceChronoDetailService], (service: AnnonceChronoDetailService) => {
        expect(service).toBeTruthy();
    }
    ));


    it('#fetchData should return value from observable', (done: DoneFn) => {
        service.fetchData(alChrono).subscribe(value => {
            expect(value).toBe('observable value');
            done();
        });
    });

});

и когда я выполняю ng test, у меня проблема во втором тесте #fetchData should return value from observable, ошибка:

AnnonceChronoDetailService > #fetchData should return value from observable


TypeError: Cannot read property 'fetchData' of undefined
    at <Jasmine>
    at UserContext.<anonymous> (http://localhost:9876/src/app/services/annonce-legale/annonce-chrono-detail.service.spec.ts?:41:17)
    at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:388:1)
    at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:288:1)
    at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/node_modules/zone.js/dist/zone.js?:387:1)
    at Zone../node_modules/zone.js/dist/zone.js.Zone.run (http://localhost:9876/node_modules/zone.js/dist/zone.js?:138:1)
    at runInTestZone (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:506:1)
    at UserContext.<anonymous> (http://localhost:9876/node_modules/zone.js/dist/zone-testing.js?:522:1)
    at <Jasmine>

Я пробую некоторые решения, такие как добавление asyn, но проблема была та же.

1 Ответ

0 голосов
/ 02 ноября 2018

Вы определяете «сервис» в первой спецификации (функция «это»), но затем пытаетесь использовать его во второй. Если вы хотите использовать переменную 'service' в каждой спецификации, что имеет смысл, то я бы посоветовал вам поместить что-то подобное в функцию beforeEach, чтобы правильно определить службу для каждой спецификации:

service = TestBed.get(AnnonceChronoDetailService);

Затем измените свою первую спецификацию на следующую:

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

Теперь ваша вторая спецификация должна работать как написано.

Обновление:

Добавление шпионов для других ваших услуг. Много способов сделать это. Вот один из них:

describe('AnnonceChronoDetailService', () => {
    const spyDecorator = jasmine.createSpyObj('UrlDecoratorService', {
        urlAPIDecorate: '/test/url',
        generateParameters: null /* set test params to return here /*
    };
    const spyFetcher = jasmine.createSpyObj('APIFetcherService', {
        fetchJson: {}
    };
    let service: AnnonceChronoDetailService;
    ...

Теперь измените ваш массив провайдеров, чтобы использовать шпионов вместо оригинальных услуг:

        providers: [
            AnnonceChronoDetailService,
            { provide: UrlDecoratorService, useValue: spyDecorator } ,
            { provide: APIFetcherService, useValue: spyFetcher },
            ]

и затем в ваших спецификациях вы можете проверить этих шпионов. Измените эти предложения на то, что вас действительно волнует:

it('#fetchData should return value from observable', () => {
    spyFetcher.fetchJson.and.returnValue(of('observable value'));
    service.fetchData(alChrono).subscribe(value => {
        expect(value).toEqual('observable value');
    });
    expect(spyDecorator.urlAPIDecorate).toHaveBeenCalled();
    expect(spyDecorator.generateParameters).toHaveBeenCalledTimes(1);
    expect(spyFetcher.fetchJson).toHaveBeenCalledWith('/test/url', /* test params defined above */);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...