Angular 如何在没有试验台的情况下编写角度元件的单元jest测试?
我对开玩笑的测试很陌生,我很困惑为什么我所有的测试都失败了 如果您知道有任何视频或文章专门帮助编写角组件、服务等的jest单元测试,而没有“测试床”,请让我知道 这是我的密码: voice-details-graph.component.tsAngular 如何在没有试验台的情况下编写角度元件的单元jest测试?,angular,unit-testing,jestjs,Angular,Unit Testing,Jestjs,我对开玩笑的测试很陌生,我很困惑为什么我所有的测试都失败了 如果您知道有任何视频或文章专门帮助编写角组件、服务等的jest单元测试,而没有“测试床”,请让我知道 这是我的密码: voice-details-graph.component.ts @Component({ selector: 'senet-voice-details-graph', templateUrl: './voice-details-graph.component.html', styleUrls: ['./vo
@Component({
selector: 'senet-voice-details-graph',
templateUrl: './voice-details-graph.component.html',
styleUrls: ['./voice-details-graph.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VoiceDetailsGraphComponent {
vm$: Observable<IVoiceSummary> = this._voiceDetailsFacade.vm$.pipe(
map(vm => vm.graphDetails)
);
constructor(private _voiceDetailsFacade: VoiceDetailsFacade) {}
setCdrFilters() {
this._voiceDetailsFacade.setCDRInitialOptions();
}
removeHyphen(phone: string) {
return phone.replace(/-|\s/g, '');
}
}
失败:
FAIL senet-voice libs/senet/voice/src/lib/features/voice-details/voice-details-graph/voice-details-graph.component.spec.ts (11.104 s)
● VoiceDetailsGraphComponent › should run #constructor()
TypeError: Cannot read property 'pipe' of undefined
13 | })
14 | export class VoiceDetailsGraphComponent {
> 15 | vm$: Observable<IVoiceSummary> = this._voiceDetailsFacade.vm$.pipe(
| ^
16 | map(vm => vm.graphDetails)
17 | );
18 |
● VoiceDetailsGraphComponent › should run #constructor()
expect(received).toBeTruthy()
Received: undefined
13 |
14 | it('should run #constructor()', () => {
> 15 | expect(component).toBeTruthy();
| ^
16 | });
17 |
18 | it('should run #setCdrFilters()', async () => {
● VoiceDetailsGraphComponent › should run #setCdrFilters()
TypeError: Cannot read property 'pipe' of undefined
13 | })
14 | export class VoiceDetailsGraphComponent {
> 15 | vm$: Observable<IVoiceSummary> = this._voiceDetailsFacade.vm$.pipe(
| ^
16 | map(vm => vm.graphDetails)
17 | );
18 |
● VoiceDetailsGraphComponent › should run #setCdrFilters()
TypeError: Cannot read property '_voiceDetailsFacade' of undefined
17 |
18 | it('should run #setCdrFilters()', async () => {
> 19 | component._voiceDetailsFacade.setCDRInitialOptions = jest.fn();
| ^
20 | component.setCdrFilters();
21 | expect(component._voiceDetailsFacade.setCDRInitialOptions).toHaveBeenCalled();
22 | });
● VoiceDetailsGraphComponent › should run #removeHyphen()
TypeError: Cannot read property 'pipe' of undefined
13 | })
14 | export class VoiceDetailsGraphComponent {
> 15 | vm$: Observable<IVoiceSummary> = this._voiceDetailsFacade.vm$.pipe(
| ^
16 | map(vm => vm.graphDetails)
17 | );
18 |
● VoiceDetailsGraphComponent › should run #removeHyphen()
TypeError: Cannot read property 'phone' of undefined
25 | const input = '1-800-999-9999';
26 | const output = '18009999999';
> 27 | component.phone.replace = jest.fn();
| ^
28 | expect(component.removeHyphen(input)).toEqual(output);
29 | expect(component.phone.replace.toHaveBeenCalled());
30 | });
FAIL senet voice libs/senet/voice/src/lib/features/voice details/voice details graph/voice-details-graph.component.spec.ts(11.104 s)
● VoiceDetailsGraphComponent›应运行#构造函数()
TypeError:无法读取未定义的属性“pipe”
13 | })
14 |导出类VoiceDetailsGraphComponent{
>15 | vm$:Observable=此。_voiceDetailsFacade.vm$.pipe(
| ^
16 |映射(vm=>vm.graphDetails)
17 | );
18 |
● VoiceDetailsGraphComponent›应运行#构造函数()
expect(已收到)。toBeTruthy()
收到:未定义
13 |
14 |它('应该运行#构造函数()',()=>{
>15 | expect(component).toBeTruthy();
| ^
16 | });
17 |
18 |它('should run#setCdrFilters()',async()=>{
● VoiceDetailsGraphComponent›应运行#setCdrFilters()
TypeError:无法读取未定义的属性“pipe”
13 | })
14 |导出类VoiceDetailsGraphComponent{
>15 | vm$:Observable=此。_voiceDetailsFacade.vm$.pipe(
| ^
16 |映射(vm=>vm.graphDetails)
17 | );
18 |
● VoiceDetailsGraphComponent›应运行#setCdrFilters()
TypeError:无法读取未定义的属性“\u voiceDetailsFacade”
17 |
18 |它('should run#setCdrFilters()',async()=>{
>19 |组件。_voiceDetailsFacade.setCDRInitialOptions=jest.fn();
| ^
20 | component.setCdrFilters();
21 |期望(组件._voiceDetailsFacade.setCDRInitialOptions).tohaveEncalled();
22 | });
● VoiceDetailsGraphComponent›应运行#removeHyphen()
TypeError:无法读取未定义的属性“pipe”
13 | })
14 |导出类VoiceDetailsGraphComponent{
>15 | vm$:Observable=此。_voiceDetailsFacade.vm$.pipe(
| ^
16 |映射(vm=>vm.graphDetails)
17 | );
18 |
● VoiceDetailsGraphComponent›应运行#removeHyphen()
TypeError:无法读取未定义的属性“phone”
25 |常数输入='1-800-999-9999';
26 |常数输出='1800999999';
>27 | component.phone.replace=jest.fn();
| ^
28 | expect(component.removehypen(input)).toEqual(output);
29 | expect(component.phone.replace.tohavebeencall());
30 | });
这就是我的解决方案:
我需要在beforeach函数中添加一个带有vm$obbservable的模拟对象
import { of } from 'rxjs';
import { VoiceDetailsGraphComponent } from './voice-details-graph.component';
describe('VoiceDetailsGraphComponent', () => {
let component: any;
beforeEach(() => {
const mockFacade = {
vm$: of({}),
};
component = new VoiceDetailsGraphComponent(mockFacade as any);
});
it('should run #constructor()', () => {
expect(component).toBeTruthy();
});
it('should run #setCdrFilters()', async () => {
component._voiceDetailsFacade.setCDRInitialOptions = jest.fn();
component.setCdrFilters();
expect(
component._voiceDetailsFacade.setCDRInitialOptions
).toHaveBeenCalled();
});
it('should run #removeHyphen()', async () => {
const input = '1-800-999-9999';
const output = '18009999999';
expect(component.removeHyphen(input)).toEqual(output);
});
});
如果您是测试新手,为什么您认为在没有测试床的情况下进行测试是一个好主意?事实并非如此。您将DI部分保留为未经测试的状态,并自行复制真实事物的工作方式。
vm$
预计用于组件构造。您没有它。@palsamsotha这是因为我们不想在这里测试服务,而只测试当前版本组件。该服务有自己的规范文件。@我工作的EstusFlask不需要文档中的测试台报价:“注意:在此需要指出的是,Angular CLI和第三方工具都使用Angular的TestBed模块生成spec文件。如果我们打算使用HTML/UI编写集成测试,则此模块非常有用,但因为集成测试是由QA团队编写的(请参阅“组件HTML/UI测试”一节)这个模块是不需要的,可以通过更简单的方法删除。事实上,将这个测试平台模块留在测试文件中可以显著增加单元测试时间。”因为构造函数需要x个参数,它只是模拟一个“参数”…如果我不这样做,那么我会得到一个linter错误。
import { of } from 'rxjs';
import { VoiceDetailsGraphComponent } from './voice-details-graph.component';
describe('VoiceDetailsGraphComponent', () => {
let component: any;
beforeEach(() => {
const mockFacade = {
vm$: of({}),
};
component = new VoiceDetailsGraphComponent(mockFacade as any);
});
it('should run #constructor()', () => {
expect(component).toBeTruthy();
});
it('should run #setCdrFilters()', async () => {
component._voiceDetailsFacade.setCDRInitialOptions = jest.fn();
component.setCdrFilters();
expect(
component._voiceDetailsFacade.setCDRInitialOptions
).toHaveBeenCalled();
});
it('should run #removeHyphen()', async () => {
const input = '1-800-999-9999';
const output = '18009999999';
expect(component.removeHyphen(input)).toEqual(output);
});
});