角度单元测试router.events

时间:2017-12-11 13:03:02

标签: angular unit-testing jasmine

我有一个组件可以更新特定路由器事件的变量。如何进行单元测试以确保以下代码正常工作?

schema.rb

路由器存根

router.events.subscribe(event => {
  if (event instanceof NavigationStart) {
    this.isLoading = true;
  } else if (event instanceof NavigationEnd || event instanceof NavigationCancel) {
    this.isLoading = false;
  } else if (event instanceof NavigationError) {
    this.isLoading = false;
    // console.error('effect error: ', error);
  }
});

2 个答案:

答案 0 :(得分:1)

我当时处在类似的情况,这就是我想出的方式:

describe('router.events', () => {
  const mockStart = of(new NavigationStart(0, '/testUrl'));
  const mockEnd = of(new NavigationEnd(0, '/testUrl', '/testUrlRedirect'));
  const mockCancel = of(new NavigationCancel(0, '/testUrl', '/testReason'));
  const mockError = of(new NavigationError(0, '/testUrl', 'test error'));

  let routerEventSpy: jasmine.Spy;
  beforeEach(() => {
    routerEventSpy = spyOn(component.router, 'events');
  });

  it('should set isLoading to true', () => {
    // Arrange
    routerEventSpy.and.returnValue(mockStart);
    component.isLoading = false; // initial value to make sure code is effective

    // Act
    // Call whatever method contains your router.events.subscribe - for example:
    component.ngOnInit(); // <-- Just an example, you should replace this with your corresponding method

    // Assert
    expect(component.isLoading).toBe(true);
  });

  it('should set isLoading to false for NavigationEnd', () => {
    // Arrange
    routerEventSpy.and.returnValue(mockEnd);
    component.isLoading = true; // initial value, see first test

    // Act
    // Call whatever method contains your router.events.subscribe - for example:
    component.ngOnInit(); // <-- Just an example, see first test

    // Assert
    expect(component.isLoading).toBe(false);
  });

  it('should set isLoading to false for NavigationCancel', () => {
    // Arrange
    routerEventSpy.and.returnValue(mockCancel);
    component.isLoading = true; // initial value, see first test

    // Act
    // Call whatever method contains your router.events.subscribe - for example:
    component.ngOnInit(); // <-- Just an example, see first test

    // Assert
    expect(component.isLoading).toBe(false);
  });

  it('should set isLoading to false for NavigationError', () => {
    // Arrange
    routerEventSpy.and.returnValue(mockError);
    component.isLoading = true; // initial value, see first test

    // Act
    // Call whatever method contains your router.events.subscribe - for example:
    component.ngOnInit(); // <-- Just an example, see first test

    // Assert
    expect(component.isLoading).toBe(false);
  });
});

一些注意事项:

  • component应该替换为存储fixture.componentInstance的内容。测试中就是this
  • 这仍然可以与上面已打断的路由器一起使用,但是它没有使用Observable及其声明的方法-spy返回的是of可观察值触发subscribe。可以使用一种用于您目的的路由器存根的方法,但是您的问题仅要求测试该逻辑和isLoading变量的方法。
  • 如果您的路由器是protectedprivate(一种很好的做法),您仍然可以使用方括号表示法来监视它-例如spyOn(component['router'], 'events')

答案 1 :(得分:1)

您需要创建一个简单的Router存根,以允许在测试期间发出各种路由器事件。

路由器存根:

// mocked source of events
const routerEventsSubject = new Subject<RouterEvent>();

const routerStub = {
    events: routerEventsSubject.asObservable()
};

describe('FooComponent', () => {
    ...

然后您只需使用该存根:

...
let router: Router;

beforeEach(() => {
    TestBed.configureTestingModule({
        providers: [
            {
                provide: Router,
                useValue: routerStub
            }
        ]
    });
    router = TestBed.inject(Router);
...

一个测试看起来像这样:

it('should be loading on a navigation start', () => {
    // create a navigation event
    routerEventsSubject.next(new NavigationStart(1, 'start'));

    expect(component.isLoading).toBeTruthy();
});