【问题标题】:Jasmine Angular component is undefinedJasmine Angular 组件未定义
【发布时间】:2019-08-06 13:24:19
【问题描述】:

我对 Angular 7 有点陌生,对它的单元测试框架 Jasmine 完全陌生

所以我一直在关注 Jasmine 的文档以及一些教程。我有一个名为TestTableComponent 的组件。现在该组件有点硬编码。无论如何,我认为我面临的问题与组件本身几乎没有任何关系,所以我在这里不包括组件的代码。

我在test-table.component.spec.ts 中创建了一个测试类。代码如下:

// Required Imports have been made. Not including as unnecessary.

describe('TestTableComponent',  async() => 
{
let component: TestTableComponent;
let fixture: ComponentFixture<TestTableComponent>;
let de: DebugElement;


beforeEach(async(() => 
{
    TestBed.configureTestingModule({declarations:[TestTableComponent],
    imports: [ReactiveFormsModule]}).compileComponents();
}));
beforeEach(() =>
{
    fixture = TestBed.createComponent(TestTableComponent);
    component = fixture.componentInstance;

    de = fixture.debugElement;
})


it('should check if data is returned by the API')
{

    const result = await component.GetEmployees;
    expect(result).toBeDefined();
}
});

这里的问题是,当我执行ng test 时,它似乎运行基于此类的测试。在浏览器的控制台中,我收到一个错误(Jasmine1 component is pending)如下:

无法读取未定义的属性GetEmployees

现在,这显然意味着TestTableComponent 永远不会被初始化。我只是想知道为什么? beforeEach 没有被执行吗?如果是,那为什么component未定义?

更新:包括组件的代码

Test-table.component.ts

import { AfterViewInit, Component, OnInit, ViewChild, Inject } from '@angular/core';
import { MatPaginator, MatSort, MatTable, MatTableDataSource, MatDialogRef, Sort, ShowOnDirtyErrorStateMatcher } from '@angular/material';
import { MatDialog } from '@angular/material/dialog';
import { TestTableItem } from './test-table-datasource';
import { HttpClient, HttpParams } from '@angular/common/http';
import { UpdateModalDialogComponent } from '../update-modal-dialog/update-modal-dialog.component';
import { MessagePopUpComponent } from '../message-pop-up/message-pop-up.component';
@Component({
selector: 'app-test-table',
templateUrl: './test-table.component.html',
styleUrls: ['./test-table.component.css']
})
export class TestTableComponent implements AfterViewInit, OnInit {
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator;
@ViewChild(MatSort, { static: false }) sort: MatSort;
@ViewChild(MatTable, { static: false }) table: MatTable<TestTableItem>;
private myCollection: TestTableItem[] = [];

dataSource = new MatTableDataSource(this.myCollection);// Observable<TestTableItem>;
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
displayedColumns = ['id', 'fname', 'salary', 'age', 'image', 'actions'];
constructor(private http: HttpClient, private dialog:MatDialog) { }


ngOnInit() {

   this.GetAllEmployees();
 }

async GetAllEmployees()
{
 this.dataSource = await this.GetEmployees();
}
public async GetEmployees()
{
 this.myCollection = await this.http.get<TestTableItem[]>('http://localhost:22371/api/employee/GetEmployees/').toPromise();
return new MatTableDataSource(this.myCollection);

}

请注意,我没有将所有函数都包含在类中,因为这会使这篇文章变得不必要地大!

【问题讨论】:

  • 你应该在测试开始时有一个fixture.detectChanges()。第一个fixture.detectChanges() 调用组件内部的onInit。不过,这可能无法完全解决您的问题。您能否也分享一下组件定义。您的组件内部是否有任何依赖项?
  • 将异步测试的设置移动到async beforeEach。您的函数正在一个单独的线程中竞速设置。异步调用发生在另一个线程上,所以如果beforeEach 启动并且测试在之后立即开始。测试在 beforeEach 初始化之前就已经等待了
  • 你的错误是这一行:const result = await component.GetEmployees;。您没有包括圆括号 ()。这就是为什么编译器会抱怨“属性未定义”,即使它是一种方法。
  • @Riv,你能解释一下吗?
  • @Erbsenkoenig,是的,我的组件有依赖项。我也会分享代码,但是,我在哪里打电话 fixture.detectChanges() ?在beforeEach(async() 或常规beforeEach 中?

标签: javascript angular jasmine


【解决方案1】:

除了错误的it() 语法@Ethan 提到。您需要将 NO_ERRORS_SCHEMA 设置为您的 TestBed,或者您需要将缺少的依赖项包含到您的 TestBed 中。

我个人更喜欢NO_ERRORS_SCHEMA 方法,因为单元测试不需要测试某些第三方库是否正常工作,但这取决于你。这种方法通常被称为对组件进行浅层测试

架构设置如下:

TestBed.configureTestingModule({
    declarations:[TestTableComponent],
    imports: [ReactiveFormsModule],
    schemas: [NO_ERRORS_SCHEMA]

}).compileComponents();

请查看nested component tests的官方文档

【讨论】:

    【解决方案2】:

    你写错了it()函数语法,它应该带第一个参数是字符串描述,第二个参数是实现你的测试的回调:

    it('should check if data is returned by the API', async(() =>{
        fixture.detectChanges();
        const result = component.GetEmployees();
        fixture.whenStable().then(()=>{
          expect(result).toBeDefined();
        })
    }))
    
    

    【讨论】:

    • 现在它抛出以下错误:Template parse errors: Can't bind to 'ngModel' since it isn't a known property of 'input'. ("Size.px]=14 style="width:70px; margin:0px 30px 5px 50px;"&gt; &lt;input matInput placeholder="ID" [ERROR -&gt;][(ngModel)]="searchId" name="searchId" value=""&gt; &lt;/mat-form-field&gt;。现在mat-field-form 是模板的一部分。那么..这实际上意味着什么?
    • 这意味着您还需要向 TestBed 提供其依赖项,在这种情况下为 FormsModule ,我也没有看到表组件中定义的 GetEmployees
    • 它大喊错误,这意味着现在it() 函数正在工作
    • 是的,你还需要提供你的组件使用的Material的模块,TestBed就像一个用于测试的NgModule,所有依赖项都需要导入
    • 我现在加入了,请重新检查
    猜你喜欢
    • 2015-02-10
    • 2023-03-12
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    相关资源
    最近更新 更多