Angular单元测试呼叫读取行为主题
我也有一个Angular类实现的ControlValueAccessor接口。
我需要100%的覆盖范围。请帮助我掩盖遗体。 第20、35、36行需要覆盖。尝试了我错过某个地方的最好的接缝。
,
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
import { TestSharedModule } from 'src/app/test/test-shared.module';
import { CommentEditorComponent } from './comment-editor.component';
describe('CommentEditorComponent', () => {
let component: CommentEditorComponent;
let fixture: ComponentFixture<CommentEditorComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
NgbPopoverModule,
TestSharedModule,
],
declarations: [CommentEditorComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CommentEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call writeValue', fakeAsync(() => {
const savedValue = spyOn(component.savedValue$, 'next');
component.writeValue('A');
expect(savedValue).toHaveBeenCalled();
}));
it('should call registerOnChange', () => {
let isCalledOnChange = false;
const onChange = () => {
isCalledOnChange = true;
};
component.registerOnChange(onChange);
expect(isCalledOnChange).toBeFalsy();
});
it('should call registerOnTouched', () => {
let isOnTouched = false;
const onChange = () => {
isOnTouched = true;
};
component.registerOnTouched(onChange);
expect(isOnTouched).toBeFalsy();
});
it('should call setDisabledState', () => {
const disable = spyOn(component.ctrl, 'disable');
component.setDisabledState(true);
expect(disable).toHaveBeenCalled();
component.setDisabledState(false);
});
});
这里是组件类
import { EventEmitter, forwardRef } from '@angular/core';
import { Component, Output } from '@angular/core';
import {
ControlValueAccessor,
FormControl,
NG_VALUE_ACCESSOR,
Validators,
} from '@angular/forms';
import { invoke } from 'lodash-es';
import { BehaviorSubject } from 'rxjs';
import { distinctUntilChanged, map, skip } from 'rxjs/operators';
@Component({
selector: 'app-comment-editor',
templateUrl: './comment-editor.component.html',
styleUrls: ['./comment-editor.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CommentEditorComponent),
multi: true,
},
],
})
export class CommentEditorComponent implements ControlValueAccessor {
onTouchedFn: () => void;
readonly savedValue$ = new BehaviorSubject<string>(null);
readonly ctrl = new FormControl(null, {
validators: Validators.required,
});
constructor() {
this.savedValue$.pipe(skip(1)).subscribe((value) => {
this.ctrl.setValue(value);
this.setDisabledState(Boolean(value));
});
}
writeValue(val: string): void {
this.savedValue$.next(val);
}
registerOnChange(fn: any): void {
this.savedValue$.pipe(skip(1), distinctUntilChanged()).subscribe(fn);
}
registerOnTouched(fn: any): void {
this.onTouchedFn = fn;
}
setDisabledState?(isDisabled: boolean): void {
invoke(this.ctrl, isDisabled ? 'disable' : 'enable');
}
}
这是覆盖范围结果
I have a angular class implemented ControlValueAccessor interface too.
I need to have 100% coverage. Please help me to cover the remain.
Line 20, 35, 36 need to be cover. Tried my best seams I have missed somewhere.
Unit test code
import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap';
import { TestSharedModule } from 'src/app/test/test-shared.module';
import { CommentEditorComponent } from './comment-editor.component';
describe('CommentEditorComponent', () => {
let component: CommentEditorComponent;
let fixture: ComponentFixture<CommentEditorComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
NgbPopoverModule,
TestSharedModule,
],
declarations: [CommentEditorComponent]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(CommentEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should call writeValue', fakeAsync(() => {
const savedValue = spyOn(component.savedValue$, 'next');
component.writeValue('A');
expect(savedValue).toHaveBeenCalled();
}));
it('should call registerOnChange', () => {
let isCalledOnChange = false;
const onChange = () => {
isCalledOnChange = true;
};
component.registerOnChange(onChange);
expect(isCalledOnChange).toBeFalsy();
});
it('should call registerOnTouched', () => {
let isOnTouched = false;
const onChange = () => {
isOnTouched = true;
};
component.registerOnTouched(onChange);
expect(isOnTouched).toBeFalsy();
});
it('should call setDisabledState', () => {
const disable = spyOn(component.ctrl, 'disable');
component.setDisabledState(true);
expect(disable).toHaveBeenCalled();
component.setDisabledState(false);
});
});
Here is the Component class
import { EventEmitter, forwardRef } from '@angular/core';
import { Component, Output } from '@angular/core';
import {
ControlValueAccessor,
FormControl,
NG_VALUE_ACCESSOR,
Validators,
} from '@angular/forms';
import { invoke } from 'lodash-es';
import { BehaviorSubject } from 'rxjs';
import { distinctUntilChanged, map, skip } from 'rxjs/operators';
@Component({
selector: 'app-comment-editor',
templateUrl: './comment-editor.component.html',
styleUrls: ['./comment-editor.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CommentEditorComponent),
multi: true,
},
],
})
export class CommentEditorComponent implements ControlValueAccessor {
onTouchedFn: () => void;
readonly savedValue$ = new BehaviorSubject<string>(null);
readonly ctrl = new FormControl(null, {
validators: Validators.required,
});
constructor() {
this.savedValue$.pipe(skip(1)).subscribe((value) => {
this.ctrl.setValue(value);
this.setDisabledState(Boolean(value));
});
}
writeValue(val: string): void {
this.savedValue$.next(val);
}
registerOnChange(fn: any): void {
this.savedValue$.pipe(skip(1), distinctUntilChanged()).subscribe(fn);
}
registerOnTouched(fn: any): void {
this.onTouchedFn = fn;
}
setDisabledState?(isDisabled: boolean): void {
invoke(this.ctrl, isDisabled ? 'disable' : 'enable');
}
}
And here is the coverage result
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您监视一种方法时,您将失去实施细节,但在调用该方法时可以访问它,该方法的调用方式以及它被调用了多少次。为了获得世界各地,您必须添加
.and.callthrough()
。尝试以下内容:
When you spy on a method, you lose implementation details but gain access to when it was called, how it was called and how many times it was called. To get the best of both world, you have to add
.and.callThrough()
.Try the following: