вопрос в том - что вы хотите проверить. это юнит тест или e2e тест? если это юнит-тест - имитируйте реактивные формы, покрывайте только свои логи c, тогда у вас нет проблем с valueChanges
, потому что он по ошибке и вы управляете им.
, если это тест e2e - вы не должны переназначать valueChanges
. Ничто не должно быть подделано / заменено, потому что это тест e2e.
Тем не менее, если вы хотите изменить valueChanges
- используйте https://github.com/krzkaczor/ts-essentials#writable
(Writable<typeof component.formField>component.formField).valueChanges = fakeInputs;
Это будет сделайте тип свойства доступным для записи.
Если это модульный тест, лично я бы проголосовал за макет реактивной формы, потому что в модульном тесте нам нужно тестировать только наш модуль, его зависимости должны быть опровергнуты / заглушены.
Внедрение частей, которые мы хотим смоделировать
В качестве опции вы можете перемещать форму как зависимость вашего компонента от провайдеров в объявлениях компонентов.
@Component({
selector: 'app-component',
templateUrl: './app-component.html',
styleUrls: ['./app-component.scss'],
providers: [
{
provide: 'form',
useFactory: () => new FormControl(),
},
],
})
export class AppComponent {
public formFieldChanged$: Observable<unknown>;
constructor(@Inject('form') public readonly formField: FormControl) {
}
public setupObservables(): void {
this.formFieldChanged$ = this.formField
.valueChanges
.pipe(
debounceTime(100),
distinctUntilChanged((a, b) => a === b),
);
}
}
Тогда вы можете просто ввести вместо теста макет вместо него.
it('should update value on debounced formField change', marbles(m => {
const values = { a: "1", b: "2", c: "3" };
const fakeInputs = m.cold('a 200ms b 50ms c', values);
const expected = m.cold('100ms a 250ms c', values);
const formInput = {
valueChanges: fakeInputs,
};
const component = new AppComponent(formInput as any as FormControl);
component.setupObservables();
m.expect(component.formFieldChanged$).toBeObservable(expected);
}));