Как написать тестовый пример Jasmine Unit для combLatest rxjs Angular

mycomponent.ts

import { Component, OnInit } from '@angular/core';
import {FormGroup,FormControl} from '@angular/forms'
import { DataServiceService } from './data-service.service';
import {combineLatest,Observable,pipe} from 'rxjs';
import {map,tap} from 'rxjs/operators';
import {Model} from './mode';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  constructor(private dataService: DataServiceService){}
  name = 'Angular';
  myForm: FormGroup;
  observableResult$: Observable<any>;

  ngOnInit(){
    this.myForm = new FormGroup({
      localId: new FormControl()
    })

  this.observableResult$ = combineLatest(
    this.myForm.get('localId').valueChanges,
    this.dataService.getDataFromURL(),
    (localIdSelected, dataFromAPI) => ({localIdSelected,dataFromAPI})).
    pipe(map(each => this.filterData(each.dataFromAPI,each.localIdSelected)));

    this.observableResult$.subscribe(value => {
      debugger
    })

  }
  filterData(dataFromAPI,localIDSelected){
    debugger
     return dataFromAPI.filter(item => item.userId > Number(localIDSelected));
    }

}

data.service.service.ts

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http'
import {Model} from './mode';
import {Observable} from 'rxjs';
@Injectable()
export class DataServiceService {

  constructor(private http:HttpClient) { }

  getDataFromURL():Observable<Model>{
    return this.http.get<Model>('https://jsonplaceholder.typicode.com/todos');
  }

}

app.component.html

<form [formGroup] = "myForm" >

<select formControlName = "localId">
  <option>1</option>
  <option>2</option>
</select>

</form>

app.spec.ts

const spyFilter = spyOn(component as any, filterData).and.callThrough();

const constAPIData$ = staticDataServiceMock.getAPIData();
                    spyOn(staticDataServiceMock, 'getAPIData').and.returnValue(
                        observableOf(countryStaticData$)
                    );
component.myForm.get('localId').setValue(1);

component.observableResult$.subscribe(value => {
expect(value[0].id==21).toBeTrue();
});

staticDatamock.ts

export class StaticDataMock{

static getAPIData(): Observable<StaticDataElements[]> {
    return [
  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },
  {
    "userId": 1,
    "id": 2,
    "title": "quis ut nam facilis et officia qui",
    "completed": false
  },
  {
    "userId": 1,
    "id": 3,
    "title": "fugiat veniam minus",
    "completed": false
  },
  {
    "userId": 1,
    "id": 4,
    "title": "et porro tempora",
    "completed": true
  }];
  }
}

Я добавил свой тестовый пример, чтобы охватить оператор combLatest и filterData в app.spec.ts, но требуемый код не работает. и мое ожидание вызова filterData не удалось. combLatest запустит событие для valueChange и получит данные из API. Я могу создать макет и setValue внутри файла спецификации, но он не работает.

Какой у Вас вопрос? Если вы хотите, чтобы кто-то помог вам в написании тестовых примеров, вам нужно четко понимать, что именно вы пытаетесь тестировать. Вам также нужно будет показать намного больше деталей, например, что такое mock.getIds() и что он возвращает, если есть другие макеты, которые вы настроили, и их реализации, детали TestBed, если вы его используете, и т. д. И т. Д.

dmcgrandle 29.11.2018 18:45

@dmcgrandle: я обновил свой вопрос, проверьте

Mithun S 01.12.2018 18:46

Спасибо, мы приближаемся. :) Меня немного смущают названия разных файлов. app.component.html - это шаблон для mycomponent.ts? Где файл mycomponent.spec.ts? Кроме того, покажите, пожалуйста, всю установку и реализацию TestBed - фактически, все файлы спецификаций, кроме тех спецификаций, которые работают и с которыми вам не нужна помощь. Вы показываете класс StaticDataMock, но в спецификации вы называете staticDataServiceMock - но не показываете, как (или даже если) эти два связаны (я предполагаю, вы вводите его в массив TestBed [провайдеры] ...)

dmcgrandle 01.12.2018 18:58
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
Promise v/s Observable в Angular
Promise v/s Observable в Angular
В системах Push производитель определяет, когда отправить данные потребителю. Потребитель не знает, когда он получит эти данные.
Подсказка RxJS [filter, skipWhile]
Подсказка RxJS [filter, skipWhile]
Эта подсказка описывает разницу между операторами filter и skipWhile из библиотеки RxJS .
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
3
3
6 491
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Я сделал несколько вещей, чтобы тест заработал (вроде как).

  • Я изменил тип метода getAPIData() в классе StaticDataMock на общедоступный, чтобы вы могли вызывать его извне класса.
  • Я попросил метод вернуть of(), превратив возвращаемое значение в Observable ваших данных.
  • Я догадался о ваших реализациях насмешки DataServiceService, подробности в Stackblitz.
  • Я создал объект Jasmine spyObject для перехвата вызовов getDataFromURL() в службе и возврата наблюдаемого, созданного вами с помощью StaticDataMock.
  • Я изменил порядок именования вещей в спецификации и сделал console.info(), чтобы показать, что component.observableResult$ никогда не излучает.

Обновлять

Согласно комментариям ниже, ссылка на Stackblitz выше была обновлена ​​и теперь работает. Вот рабочая спецификация из этого Stackblitz:

it('should change return of service.function1() only', () => {
    fixture.detectChanges(); 
    component.observableResult$.subscribe(value => {
        console.info('observable Emitted, value is ', value);
        expect(value[0].id==1).toBe(true); 
    });
    component.myForm.get('localId').setValue(1);
});

Ключ к этому заключался в том, чтобы сначала настроить подписку, а затем выдать новое значение в форме, которое обновит combineLatest() и выполнит код внутри subscribe().

Я рад, что это сработало!

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

Mithun S 03.12.2018 13:22

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

dmcgrandle 03.12.2018 17:23

Я пытался правильно связать наблюдаемые с помощью combLatest (), у меня есть 2 элемента управления: один для страны, другой для состояний, когда страна изменяется в первом элементе управления (первый аргумент combLatest), он должен запускатьcommonLatest и извлекать соответствующие состояния из страны service (2-й аргумент combLatest). Второй результат аргумента conatins Массив объекта, затем я должен передать его по конвейеру и отфильтровать состояния с использованием выбранной страны (с использованием выбранной страны - первого параметра combLatest)

Mithun S 04.12.2018 07:56

Я правильно реализовал это, но не получил покрытия тестового примера.

Mithun S 04.12.2018 08:01

У вас есть это в Stackblitz, чтобы я мог посмотреть?

dmcgrandle 04.12.2018 08:06
stackblitz.com/edit/stackoverflow-q-53538362-ebvdtj Это почти то же самое, что и ссылка, которую вы предоставили, не может достичь ожидаемого блока внутри тестового примера
Mithun S 04.12.2018 08:15

Получил это, просто переместив component.myForm.get('localId').setValue(1); после подписки. Необходимо думать асинхронно - как только подписка будет настроена, ЗАТЕМ мы инициируем новую эмиссию с setValue(1), которая вызовет выполнение подписки. :)

dmcgrandle 04.12.2018 09:06

Большое спасибо @dmcgrandle, наконец-то это сработало !! Можете ли вы обновить то же самое в Stackblitz и опубликовать в качестве ответа, чтобы я мог принять его, тогда это будет очень интересно и для других !!

Mithun S 04.12.2018 09:49

Я сделаю завтра. Рад, что мы разобрались. :)

dmcgrandle 04.12.2018 10:07

Другие вопросы по теме