Angular 单元测试无法读取未定义的属性
Angular Unit test Cannot read properties of undefined
我正在尝试对一个组件进行单元测试,
组件和页面正在导入表单 @bloomreach/spa-sdk
export class ThinComponent implements OnInit {
@Input() component!: BrComponent;
componentModels: any;
page: Page;
constructor() {}
ngOnInit() {
this.componentModels = this.component.getModels();
}
getContents(contentRef) {
if (contentRef && contentRef.$ref) {
this.content = this.page?.getContent(contentRef).getData();
}
}
}
我的单元测试像
it('should create', () => {
spyOn(component.component, 'getModels').and.returnValue({foo: 'bar'});
fixture.detectChanges();
expect(component).toBeTruthy();
});
抛出和错误TypeError: Cannot read properties of undefined (reading 'getModels')
Ruslan Lekhman 是对的,您需要初始化 component
输入,我认为 spyOn
不适合它。 spyOn
仅适用于 public 方法。
试试这个:
it('should create', () => {
component.component = { getModels: () => ({ foo: 'bar' }) };
fixture.detectChanges();
expect(component).toBeTruthy();
});
编辑:
尝试将 mockPage
更改为这样的内容。
const getDataSpy = jasmine.createSpy('getData');
mockPage = { getContent: () => ({ getData: getDataSpy }) };
....
expect(getDataSpy).and.callFake(() => { return 'test'; });
编辑
Component.ts
import { Component, Input, VERSION } from '@angular/core';
import { Component as BrComponent, Page } from '@bloomreach/spa-sdk';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
name = 'Angular ' + VERSION.major;
@Input() component!: BrComponent;
page: Page;
componentModels: any;
public content: any;
public image: string;
public inViewport = false;
constructor() {}
get configuration() {
return this.component.getParameters();
}
ngOnInit() {
this.componentModels = this.component?.getModels();
if (this.componentModels) {
this.getContents(this.componentModels.document);
}
}
getContents(contentRef) {
if (contentRef && contentRef.$ref) {
this.content = this.page?.getContent(contentRef).getData();
if (this.content) {
if (this.content.image) {
this.image = this.getImageUrl(this.content.image);
}
}
}
}
getImageUrl($ref): string {
return this.page.getContent($ref).getUrl();
}
onVisible(event) {
this.inViewport = true;
}
}
Component.spec.ts
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AppComponent } from './AppComponent';
import { Component as BrComponent, Page } from '@bloomreach/spa-sdk';
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
component.component = {
getModels: () => ({ document: { $ref: {} } }),
getParameters: () => ({}),
};
component.page = {
getContent: () => ({
getData: () => ({ image: 'abc' }),
getUrl: () => 'xyz',
}),
};
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should test ngOninit', () => {
spyOn(component, 'getContents').and.callFake(() => null);
component.ngOnInit();
expect(component.getContents).toHaveBeenCalled();
});
it('should test getContents', () => {
component.getContents(component.componentModels.document);
expect(component.image).toBe('xyz');
});
});
我正在尝试对一个组件进行单元测试, 组件和页面正在导入表单 @bloomreach/spa-sdk
export class ThinComponent implements OnInit {
@Input() component!: BrComponent;
componentModels: any;
page: Page;
constructor() {}
ngOnInit() {
this.componentModels = this.component.getModels();
}
getContents(contentRef) {
if (contentRef && contentRef.$ref) {
this.content = this.page?.getContent(contentRef).getData();
}
}
}
我的单元测试像
it('should create', () => {
spyOn(component.component, 'getModels').and.returnValue({foo: 'bar'});
fixture.detectChanges();
expect(component).toBeTruthy();
});
抛出和错误TypeError: Cannot read properties of undefined (reading 'getModels')
Ruslan Lekhman 是对的,您需要初始化 component
输入,我认为 spyOn
不适合它。 spyOn
仅适用于 public 方法。
试试这个:
it('should create', () => {
component.component = { getModels: () => ({ foo: 'bar' }) };
fixture.detectChanges();
expect(component).toBeTruthy();
});
编辑:
尝试将 mockPage
更改为这样的内容。
const getDataSpy = jasmine.createSpy('getData');
mockPage = { getContent: () => ({ getData: getDataSpy }) };
....
expect(getDataSpy).and.callFake(() => { return 'test'; });
编辑
Component.ts
import { Component, Input, VERSION } from '@angular/core';
import { Component as BrComponent, Page } from '@bloomreach/spa-sdk';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
name = 'Angular ' + VERSION.major;
@Input() component!: BrComponent;
page: Page;
componentModels: any;
public content: any;
public image: string;
public inViewport = false;
constructor() {}
get configuration() {
return this.component.getParameters();
}
ngOnInit() {
this.componentModels = this.component?.getModels();
if (this.componentModels) {
this.getContents(this.componentModels.document);
}
}
getContents(contentRef) {
if (contentRef && contentRef.$ref) {
this.content = this.page?.getContent(contentRef).getData();
if (this.content) {
if (this.content.image) {
this.image = this.getImageUrl(this.content.image);
}
}
}
}
getImageUrl($ref): string {
return this.page.getContent($ref).getUrl();
}
onVisible(event) {
this.inViewport = true;
}
}
Component.spec.ts
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { AppComponent } from './AppComponent';
import { Component as BrComponent, Page } from '@bloomreach/spa-sdk';
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
component.component = {
getModels: () => ({ document: { $ref: {} } }),
getParameters: () => ({}),
};
component.page = {
getContent: () => ({
getData: () => ({ image: 'abc' }),
getUrl: () => 'xyz',
}),
};
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should test ngOninit', () => {
spyOn(component, 'getContents').and.callFake(() => null);
component.ngOnInit();
expect(component.getContents).toHaveBeenCalled();
});
it('should test getContents', () => {
component.getContents(component.componentModels.document);
expect(component.image).toBe('xyz');
});
});