在反应式表单模块的 auditTime 方法的订阅块中测试值
test values within a subscribe block of a reactive form module's auditTime method
我正在尝试在使用 rxjs auditTime
方法的 angular4/typescript 茉莉花单元测试中测试 .subscribe
块内的值。我已经阅读了很多与此类似的帖子,但似乎并没有让我进入那个街区。
我有以下示例组件:
address.component.ts:
export class AddressComponent implements OnInit {
public form: FormGroup;
constructor (
private fb: FormBuilder
) {}
public ngOnInit (): void {
this.createForm();
}
public createForm (): void {
this.form = this.fb.group({
lineOne: [this.address.lineOne],
});
this.form.valueChanges.auditTime(500).subscribe(() => {
this.address.lineOne = this.form.value.lineOne;
});
}
}
address.component.html:
<div class="address">
<form [formGroup]="form">
<div class="row">
<div class="col-12 address-body">
<div class="form-group-main">
<div class="row">
<div class="address-input col-12">
<label for="address-line-one" [class.required]="isMandatory">Address Line 1</label>
<input class="form-control" id="address-line-one" type="text" formControlName="lineOne">
</div>
</div>
</div>
</div>
<div class="col-12 address-body">
<display-address [body]="address.lineOne"></display-address>
</div>
<div class="col-12">
<button class="btn btn-full-width btn-primary btn-sm btn-edit" id="address-edit" type="button" (click)="...">Edit</button>
</div>
</div>
</form>
</div>
address.component.spec.ts:
describe('Address Component', () => {
let component: AddressComponent;
let fixture: ComponentFixture<AddressComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AddressComponent],
imports: [ReactiveFormsModule],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(AddressComponent);
component = fixture.componentInstance;
});
}));
it('should update address', fakeAsync(() => {
component.address = {lineOne: 'street'};
fixture.detectChanges();
//do something..
}));
});
假设上面的设置正确并且我没有遗漏任何明显的东西,这就是为什么我的测试从来没有提供正确的结果,我已经尝试用以下想法修改我的测试:
监视 auditTime 并通过以下方式调用:
spyOn(component.form.valueChanges, 'auditTime').and.callThrough();
监视 auditTime 并调用假函数:
spyOn(component.form.valueChanges,'auditTime').and.callFake(()=> {
return {
subscribe: () => {}
}
});
监视 auditTime 并返回一个值 Observable.of:
spyOn(component.form.valueChanges,'auditTime').and.returnValue(Observable.of('hello'));
直接调用:
component.form.valueChanges.auditTime().subscribe(result => {
//never get in here
});
尝试使用 tick()
等待并尝试使用 flushMicrotasks()
.
刷新
监视 createForm 函数:
spyOn(component, 'createForm').and.callFake(() => {
return Observable.of('hello');
});
如果我使用以下内容,使用 debugElement 访问和更新 lineOne 总是 returns 错误:
const el = fixture.nativeElement.querySelector(By.css('#address-line-one'));
el.value = 'something';
el.dispatchEvent(new Event('input'));
fixture.detectChanges();
因为它看起来只能看到 html 和 <display-address></display-address>
的编辑按钮,这表明它当时可能没有编译。
我也尝试过将所有内容包装在:
fixture.whenStable().then(() => {
// do something..
});
现在我没主意了,如果有人能理解以上内容并为我指明正确的方向,那就太好了。
解决方案
感谢 Amir,在这个特定示例中,我似乎过度思考了为此所需的答案,使用 NO_ERRORS_SCHEMA
隐藏了真正的问题。结果我需要导入 <display-address>
需要的组件:
imports: [ReactiveFormsModule, DisplayAddressComponent],
这允许模板正确编译,这意味着我可以看到所有表单值,而不仅仅是 <display-address>
。按照建议,我使用 fakeAsync
和 tick(600)
的组合来发出对表单的更改:
it('should update address', fakeAsync(() => {
component.address = {lineOne: 'street'};
fixture.detectChanges();
expect(component.address.lineOne).toBe('street');
component.form.controls['lineOne'].setValue('test');
tick(600);
expect(component.address.lineOne).toBe('test');
}));
如果有人有类似的问题。
好的,我只是post这里是我的假设,检查它是否有帮助:
- 直接调用 ngOnInit() 或在 之后使用 detectChanges()
创建组件;
- 仅当您使用 fakeAsync + tick(600);
时,测试才能 同步
- After 你执行 tick(600) 尝试将值发送到 this.form.valueChanges,您可以通过 替换 FormBuilder 来做到这一点,这样它将 return 对象与您自己的发射器(主题)或通过 在 [=54] 中找到一个元素=] 和 使用 DOM 事件输入值 。
- 如果您决定 使用 html 作为输入 , 删除 NO_ERRORS_SCHEMA 并查看可能未呈现因为一些错误(因为你说 html 的那部分不存在)。
我正在尝试在使用 rxjs auditTime
方法的 angular4/typescript 茉莉花单元测试中测试 .subscribe
块内的值。我已经阅读了很多与此类似的帖子,但似乎并没有让我进入那个街区。
我有以下示例组件:
address.component.ts:
export class AddressComponent implements OnInit {
public form: FormGroup;
constructor (
private fb: FormBuilder
) {}
public ngOnInit (): void {
this.createForm();
}
public createForm (): void {
this.form = this.fb.group({
lineOne: [this.address.lineOne],
});
this.form.valueChanges.auditTime(500).subscribe(() => {
this.address.lineOne = this.form.value.lineOne;
});
}
}
address.component.html:
<div class="address">
<form [formGroup]="form">
<div class="row">
<div class="col-12 address-body">
<div class="form-group-main">
<div class="row">
<div class="address-input col-12">
<label for="address-line-one" [class.required]="isMandatory">Address Line 1</label>
<input class="form-control" id="address-line-one" type="text" formControlName="lineOne">
</div>
</div>
</div>
</div>
<div class="col-12 address-body">
<display-address [body]="address.lineOne"></display-address>
</div>
<div class="col-12">
<button class="btn btn-full-width btn-primary btn-sm btn-edit" id="address-edit" type="button" (click)="...">Edit</button>
</div>
</div>
</form>
</div>
address.component.spec.ts:
describe('Address Component', () => {
let component: AddressComponent;
let fixture: ComponentFixture<AddressComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AddressComponent],
imports: [ReactiveFormsModule],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(AddressComponent);
component = fixture.componentInstance;
});
}));
it('should update address', fakeAsync(() => {
component.address = {lineOne: 'street'};
fixture.detectChanges();
//do something..
}));
});
假设上面的设置正确并且我没有遗漏任何明显的东西,这就是为什么我的测试从来没有提供正确的结果,我已经尝试用以下想法修改我的测试:
监视 auditTime 并通过以下方式调用:
spyOn(component.form.valueChanges, 'auditTime').and.callThrough();
监视 auditTime 并调用假函数:
spyOn(component.form.valueChanges,'auditTime').and.callFake(()=> {
return {
subscribe: () => {}
}
});
监视 auditTime 并返回一个值 Observable.of:
spyOn(component.form.valueChanges,'auditTime').and.returnValue(Observable.of('hello'));
直接调用:
component.form.valueChanges.auditTime().subscribe(result => {
//never get in here
});
尝试使用 tick()
等待并尝试使用 flushMicrotasks()
.
监视 createForm 函数:
spyOn(component, 'createForm').and.callFake(() => {
return Observable.of('hello');
});
如果我使用以下内容,使用 debugElement 访问和更新 lineOne 总是 returns 错误:
const el = fixture.nativeElement.querySelector(By.css('#address-line-one'));
el.value = 'something';
el.dispatchEvent(new Event('input'));
fixture.detectChanges();
因为它看起来只能看到 html 和 <display-address></display-address>
的编辑按钮,这表明它当时可能没有编译。
我也尝试过将所有内容包装在:
fixture.whenStable().then(() => {
// do something..
});
现在我没主意了,如果有人能理解以上内容并为我指明正确的方向,那就太好了。
解决方案
感谢 Amir,在这个特定示例中,我似乎过度思考了为此所需的答案,使用 NO_ERRORS_SCHEMA
隐藏了真正的问题。结果我需要导入 <display-address>
需要的组件:
imports: [ReactiveFormsModule, DisplayAddressComponent],
这允许模板正确编译,这意味着我可以看到所有表单值,而不仅仅是 <display-address>
。按照建议,我使用 fakeAsync
和 tick(600)
的组合来发出对表单的更改:
it('should update address', fakeAsync(() => {
component.address = {lineOne: 'street'};
fixture.detectChanges();
expect(component.address.lineOne).toBe('street');
component.form.controls['lineOne'].setValue('test');
tick(600);
expect(component.address.lineOne).toBe('test');
}));
如果有人有类似的问题。
好的,我只是post这里是我的假设,检查它是否有帮助:
- 直接调用 ngOnInit() 或在 之后使用 detectChanges() 创建组件;
- 仅当您使用 fakeAsync + tick(600); 时,测试才能 同步
- After 你执行 tick(600) 尝试将值发送到 this.form.valueChanges,您可以通过 替换 FormBuilder 来做到这一点,这样它将 return 对象与您自己的发射器(主题)或通过 在 [=54] 中找到一个元素=] 和 使用 DOM 事件输入值 。
- 如果您决定 使用 html 作为输入 , 删除 NO_ERRORS_SCHEMA 并查看可能未呈现因为一些错误(因为你说 html 的那部分不存在)。