问题描述
我目前正在尝试模拟 Angular 单元测试的输入属性.不幸的是,我无法进一步了解并反复收到以下错误消息:
类型错误:无法读取未定义的属性数据"
我的 HTML 模板如下所示
<div class="row"><div class="col-12"><plot [data]="graph.data" [layout]="graph.layout"></plot>
我目前正在尝试模拟 Angular 单元测试的输入属性.不幸的是,我无法进一步了解并反复收到以下错误消息:
类型错误:无法读取未定义的属性数据"
我的 HTML 模板如下所示
<div class="row"><div class="col-12"><plot [data]="graph.data" [layout]="graph.layout"></plot>
我的组件是这样的:
...导出类 ChartComponent 实现 OnInit {@Input() currentChart: 图表;当前位置数据:任意;公共图 = {数据: [{类型:'酒吧',x: [1, 2, 3],y: [10, 20, 30],}],布局: {title: '一个简单的图表',},配置:{滚动缩放:真}};...}
我的单元测试现在看起来很基本,但仍然抛出提到的错误:
describe('ChartComponent', () => {让组件:ChartComponent;让夹具: ComponentFixture;beforeEach(async(() => {TestBed.configureTestingModule({声明:[图表组件],进口:[//我的进口]}).compileComponents();}));beforeEach(() => {夹具 = TestBed.createComponent(ChartComponent);组件 = 夹具.componentInstance;夹具.detectChanges();});it('应该创建', () => {期望(组件).toBeTruthy();});});
我尝试了不同的方法来模拟数据属性和 currentChart
@Input
.
实现这一目标并修复单元测试的正确方法是什么?
输入属性就像任何变量一样工作.在您的 beforeEach 中,您可以将其设置为一个值
beforeEach(() => {夹具 = TestBed.createComponent(ExplorerChartViewComponent);组件 = 夹具.componentInstance;component.currentChart = someChart;//在第一次detectChanges之前设置输入夹具.detectChanges();});
使用我的首选方法,您将拥有一个类似于
的 TestHost 组件@Component({选择器:'app-testhost-chart',模板:`<app-chart [currentChart]=chart></app-chart>`,//或者任何你的图表组件选择器})导出类 TestHostComponent {图表 = 新图表();}
然后切换到创建新的测试主机.
声明: [ChartComponent, TestHostComponent ],...beforeEach(() => {夹具 = TestBed.createComponent(TestHostComponent);组件 = fixture.debugElement.children[0].componentInstance;夹具.detectChanges();});
但是我想我看到了您可能遇到的另外两个问题.特别是因为您正在分配图表
declarations: [ChartComponent],
但创建 fixture = TestBed.createComponent(ExplorerChartViewComponent);
我认为它应该 TestBed.createComponent(ChartComponent)
,除非这是复制/粘贴问题.<plot [data]="graph.data" [layout]="graph.layout"></plot>
表示您不是绘图组件声明.您需要为绘图声明一个组件.我建议做一些与 TestHostComponent 非常相似的事情,但它具有与真实 PlotComponent 相同的所有公共属性,这样您就不会将 PlotComponent 的真实功能和依赖项带入 ChartComponent 的单元测试中.I am currently trying to mock input properties for an Angular unit test. Unfortunately, I can not get any further and repeatedly receive the following error message:
My HTML Template looks like this
<div class="container-fluid">
<div class="row">
<div class="col-12">
<plot [data]="graph.data" [layout]="graph.layout"></plot>
</div>
</div>
</div>
My Component like this:
...
export class ChartComponent implements OnInit {
@Input() currentChart: Chart;
currentLocationData: any;
public graph = {
data: [
{
type: 'bar',
x: [1, 2, 3],
y: [10, 20, 30],
}
],
layout: {
title: 'A simple chart',
},
config: {
scrollZoom: true
}
};
...
}
My unit-test looks very basic for now, but still throws the mentioned error:
describe('ChartComponent', () => {
let component: ChartComponent;
let fixture: ComponentFixture<ChartComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ChartComponent],
imports: [
// My imports
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
I tried different ways to mock the data property and the currentChart
@Input
.
What is the right way to achieve this and fix the unit-test?
The input property works just like any variable. In your beforeEach you could set it to a value
beforeEach(() => {
fixture = TestBed.createComponent(ExplorerChartViewComponent);
component = fixture.componentInstance;
component.currentChart = someChart; // set input before first detectChanges
fixture.detectChanges();
});
You can read more about this here. I prefer this approach.
With my preferred approach you would have a TestHost component that would look something like
@Component({
selector: 'app-testhost-chart',
template: `<app-chart [currentChart]=chart></app-chart>`, // or whatever your Chart Component Selector is
})
export class TestHostComponent {
chart = new Chart();
}
Then change over to creating the new test host.
declarations: [ChartComponent, TestHostComponent ],
...
beforeEach(() => {
fixture = TestBed.createComponent(TestHostComponent );
component = fixture.debugElement.children[0].componentInstance;
fixture.detectChanges();
});
However I think I see two other issues you might have. Especially since you are assigning the graph
declarations: [ChartComponent],
but creating fixture = TestBed.createComponent(ExplorerChartViewComponent);
I would think it should TestBed.createComponent(ChartComponent)
, unless that is a copy/paste issue.<plot [data]="graph.data" [layout]="graph.layout"></plot>
which indicates a plot component that you are not declaring. You will need to declare a component for plot. I'd suggest doing something very similar to the TestHostComponent but one that has all the same public properties as your real PlotComponent, that way you aren't bringing the real functionality and dependencies of PlotComponent into your unit test for ChartComponent.
这篇关于(Angular Unit-Test) 如何在 Jasmin 中模拟输入属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!