Angular2 + Jasmine:测试路由器事件



有人可以帮我了解如何对下面的应用程序组件进行单元测试吗?这是一个 Angular 2 应用程序。

应用程序

import { Component, OnInit }     from '@angular/core';
import { Router, NavigationEnd, NavigationStart, NavigationCancel, NavigationError, RoutesRecognized } from '@angular/router';
import { DataService }           from '../services/data';
@Component({
  selector: 'app',
  template: '<messages></messages><router-outlet></router-outlet>',
  providers: [DataService]
})
export class AppComponent implements OnInit {
  constructor(private router: Router, private data: DataService) {}
  public ngOnInit(): void {
    this.router.events.subscribe((event: NavigationStart | NavigationEnd | NavigationCancel | NavigationError | RoutesRecognized) => {
        if (!(event instanceof NavigationEnd)) { return; }
        document.body.scrollTop = 0;
    });
    window.addEventListener(
        "offline", () => {
            if (this.data.settings.offlineEnabled) {
                this.data.toggleOffline();
                this.data.displayMessage("Internet connection lost, switching to offline mode.", "failure")
            } else {
                this.data.displayMessage("Internet connection lost", "failure")
            }
        }, false,
      );
  }
}

到目前为止,我得到了什么:

app.spec.ts

import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { AppComponent } from './app'
import { RouterTestingModule } from '@angular/router/testing';
import { MessagesComponent } from './messages/messages';
import { DataService }           from '../services/data';
/* Tests */
export class MockDataService {}
describe('Component: App', () => {
  let mockData = new MockDataService();
  let component: AppComponent;
  let dataService: DataService;
  let fixture: ComponentFixture<AppComponent>;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent,
        MessagesComponent
      ],
      providers: [
        { provide: DataService, useValue: mockData }
      ]
    }).compileComponents();
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    dataService = TestBed.get(DataService);
  }));
  it('should create the component', () => {
    expect(component).toBeTruthy();
  });
});

我收到错误: Failed: No provider for e!但是,在我看来,我正在导入组件实例化所需的所有内容。

我想知道这是否是 1( 要么RouterTestingModule不知道router.events.subscribe;或者,2(未定义window

有什么想法吗?

谢谢!

编辑 1:

似乎导致我问题的行是这样的:

@Component({
  ...,
  ...,
  providers: [DataService]
})

看起来 Jasmine 正在将MockDataService对象注入 app.component 构造函数中,但它没有为提供程序注入对象。 Jasmine正在提供具体的DataService实施。

如何将MockDataService注入app.component的提供程序?

您的问题可能出现,因为您还在单元测试中声明了 MessagesComponent。Angular 将尝试更新此类的实例,如果您没有为 MessagesComponent 使用的服务注入模拟,那么这可能会导致您的错误。

但是,由于您正在对 AppComponent 进行单元测试,因此您不希望将消息组件添加到声明中,因为正如您所经历的那样,所有内容似乎都在 AppComponent 中工作,但组件的依赖项导致测试失败。解决此问题的最简单方法是将NO_ERRORS_SCHEMA添加到测试模块中,如下所示:

TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        { provide: DataService, useValue: mockData }
      ],
      schemas: [
        NO_ERRORS_SCHEMA
      ]
    }).compileComponents();

这将防止 Angular 编译器抱怨代码中的自定义 HTML 标记,例如标记。

最新更新