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


![Подсказка RxJS [filter, skipWhile]](https://i.imgur.com/QlvZflrb.jpeg)

Хорошо, чтобы попытаться помочь вам в этом, я пошел дальше и настроил Stackblitz с данными, которые вы уже предоставили. Вот ссылка на сайт.
Я сделал несколько вещей, чтобы тест заработал (вроде как).
getAPIData() в классе StaticDataMock на общедоступный, чтобы вы могли вызывать его извне класса.of(), превратив возвращаемое значение в Observable ваших данных.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.
Да, это то, что я имел в виду выше при обсуждении наблюдаемого, которое трудно удержать во время тестирования, как вы его закодировали. Вероятно, его нужно реорганизовать, но только вы знаете, что на самом деле пытается выполнить этот код - мне не ясно из того, что вы опубликовали до сих пор.
Я пытался правильно связать наблюдаемые с помощью combLatest (), у меня есть 2 элемента управления: один для страны, другой для состояний, когда страна изменяется в первом элементе управления (первый аргумент combLatest), он должен запускатьcommonLatest и извлекать соответствующие состояния из страны service (2-й аргумент combLatest). Второй результат аргумента conatins Массив объекта, затем я должен передать его по конвейеру и отфильтровать состояния с использованием выбранной страны (с использованием выбранной страны - первого параметра combLatest)
Я правильно реализовал это, но не получил покрытия тестового примера.
У вас есть это в Stackblitz, чтобы я мог посмотреть?
Получил это, просто переместив component.myForm.get('localId').setValue(1); после подписки. Необходимо думать асинхронно - как только подписка будет настроена, ЗАТЕМ мы инициируем новую эмиссию с setValue(1), которая вызовет выполнение подписки. :)
Большое спасибо @dmcgrandle, наконец-то это сработало !! Можете ли вы обновить то же самое в Stackblitz и опубликовать в качестве ответа, чтобы я мог принять его, тогда это будет очень интересно и для других !!
Я сделаю завтра. Рад, что мы разобрались. :)
Какой у Вас вопрос? Если вы хотите, чтобы кто-то помог вам в написании тестовых примеров, вам нужно четко понимать, что именно вы пытаетесь тестировать. Вам также нужно будет показать намного больше деталей, например, что такое
mock.getIds()и что он возвращает, если есть другие макеты, которые вы настроили, и их реализации, детали TestBed, если вы его используете, и т. д. И т. Д.