简体   繁体   English

如何在 Angular 2 中测试 *ngFor?

[英]How to test *ngFor in Angular 2?

I am new to Angular and created To-Do Application.我是 Angular 的新手并创建了待办事项应用程序。 I tried to find the solution at many places even the Testing documentation我试图在许多地方甚至测试文档中找到解决方案
I am testing a component.我正在测试一个组件。 That bring data from mongodb, I have mocked that data though.这带来了来自 mongodb 的数据,不过我已经嘲笑了这些数据。

The following is the HTML of template (using bootstrap):以下是模板的HTML(使用bootstrap):

<li class="list-group-item" *ngFor="let task of tasks">
    <div class=" task-date">{{task.date}}</div>
</li>

The below is the component code (I'm adding only sub-part):以下是组件代码(我只添加了子部分):

export class ShowTaskComponent extends OnInit{

tasks:Task[];

ngOnInit() {
  setInterval(() => {this.refreshTasks()}, 3000);
}

constructor(private appService: AppService, private _router:Router){
  super();
  this.refreshTasks();
}

refreshTasks = function() {

  this.appService.retrieveDataFromServer().subscribe((data: any) => {

    //this.appService.taskArray = data;

    this.tasks = data;

  });

};
}

Now I'm adding the test code (.spec.ts file's sub part) ... To explain well, all of the code (excluding imports):现在我正在添加测试代码(.spec.ts 文件的子部分)......为了解释清楚,所有代码(不包括导入):

  let comp: ShowTaskComponent;
  let fixture: ComponentFixture<ShowTaskComponent>;
  let service: AppService;
  let router: Router;

  let debugTaskTitle: DebugElement[];
  let taskTitles: any[];

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ShowTaskComponent],
      providers: [AppService],
      imports: [....]
    })
      .compileComponents();
  }));

  beforeEach( () => {

    fixture = TestBed.createComponent(ShowTaskComponent);
    service = fixture.debugElement.injector.get(AppService);
    router = fixture.debugElement.injector.get(Router);

    let dummyTasks: any[] = [
      {
        "date": "12 October 2017",
        "title": "Demo task 1",
        "description": "Demo task 1 desc",
        "priority" : "High",
        "_id" : "1"
      },
      {
        "date": "1 January 2018",
        "title": "Demo task 2",
        "description": "Demo task 2 desc",
        "priority" : "Low",
        "_id" : "2"
      }
    ];

    spyOn(service, 'retrieveDataFromServer').and.returnValue(Observable.of<any[]>(dummyTasks));


    fixture = TestBed.createComponent(ShowTaskComponent);
    comp = fixture.componentInstance;
    console.log("----------------------------> comp ", comp);

    debugTaskTitle = fixture.debugElement.queryAll(By.css('div.task-title'));
    console.log("----------------------------> debugTaskTitle ", debugTaskTitle);

    let counter: number = 0;

    for(let title of debugTaskTitle) {
      taskTitles.push(title.nativeElement);
      taskTitles[counter].innerText = dummyTasks[counter].title;
      counter ++;
    }
  });

  //This test fails because taskTitles is undefined!
  it('test whether a correct test has loaded', () =>{

    expect(taskTitles).toBe(["Demo task 1", "Demo task 2"]);
  });

The problem comes with debugTaskTitle .问题来自debugTaskTitle This is empty array, when I try to initialise it with fixture.debugElement.queryAll(By.css()) .这是空数组,当我尝试使用fixture.debugElement.queryAll(By.css())初始化它时。

I tried to print it on console (look at long --------> arrows) and it is empty array.我试图在控制台上打印它(看长 --------> 箭头),它是空数组。

The object of the component comp is created and is doing great.组件comp的对象已创建并且运行良好。

Can anybody suggest me where I'm wrong?有人可以告诉我我错在哪里吗? I'm late in submitting this assignment by three days.我迟到了三天才提交这个作业。 Any help will be great.任何帮助都会很棒。

Whole code is atgithub repo整个代码在github repo

Also, I don't see anything on browser when I run only first test.另外,当我只运行第一次测试时,我在浏览器上看不到任何东西。 It should show tasks on browser!它应该在浏览器上显示任务!

So does that mean *ngFor doesn't populate the content on page once .compileComponents();那么这是否意味着 *ngFor 不会一次填充页面上的内容.compileComponents(); has been called to generate CSS and HTML within first beforeEach() ?已被调用在 first beforeEach()生成 CSS 和 HTML ?

Since retrieveDataFromServer returns an Observable, you need to wait for the async task to resolve.由于retrieveDataFromServer返回一个Observable,您需要等待异步任务解析。 For that you can wrap the beforeEach in async , just like the one above it.为此,您可以将 beforeEach 包装在async ,就像上面的那个一样。 Then you need to wait for it to stabilize然后你需要等待它稳定下来

fixture = TestBed.createComponent(ShowTaskComponent);
comp = fixture.componentInstance;

fixture.whenStable().then(() => {
    // after something in the component changes, you should detect changes
    fixture.detectChanges();

    // everything else in the beforeEach needs to be done here.
    debugTaskTitle = fixture.debugElement.queryAll(By.css('div.task-title'));
    ...
})

UPDATE更新

Note that it is now recommended to use fakeAsync over async now.请注意,现在建议使用fakeAsync不是async Unless the test makes an XHR request, which fakeAsync cannot handle, fakeAsync is the preferred method to use when testing asynchronous code.除非测试发出一个fakeAsync无法处理的 XHR 请求, fakeAsync fakeAsync是测试异步代码时使用的首选方法。 What fakeAsync does is allow you to write code as if it was synchronous and let you control when to complete the async test. fakeAsync作用是允许您像同步代码一样编写代码,并让您控制何时完成异步测试。 Some test code might look something like一些测试代码可能看起来像

import { fakeAsync } from '@angular/core/testing';

it('should...', fakeAsync(() => {
  fixture = TestBed.createComponent(ShowTaskComponent);
  comp = fixture.componentInstance;

  comp.callSomeAsyncMethod();
  tick();

  fixture.detectChanges();
  // assertions
}));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM