简体   繁体   English

Angular 单元测试 router.events

[英]Angular Unit test router.events

I have a component that updates a variable on specific router events.我有一个组件可以更新特定路由器事件的变量。 How do I unit test to make sure the code below works correctly?我如何进行单元测试以确保下面的代码正常工作?

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);
  }
});

Router stub路由器存根

class MockRouter {
    navigate = jasmine.createSpy('navigate');
    start = new NavigationStart(0, '/home');
    end = new NavigationEnd(1, '/home', '/dashboard');
    events = new Observable(observer => {
      observer.next(this.start);
      observer.next(this.end);
      observer.complete();
    });
  }

I was in a similar situation, and this is how I figured it out:我遇到了类似的情况,这就是我想出来的:

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);
  });
});

A few notes:一些注意事项:

  • component should be replaced with whatever you store the fixture.componentInstance in. It is the this in your tests. component应该替换为您存储fixture.componentInstance任何内容。这是您测试中的this
  • This would still work with a router like you have stubbed above, but it isn't using the Observable and its methods that you have declared - the spy is returning of observables to trigger the subscribe .这与路由器就像你在上面存根,但不使用,仍能正常工作Observable的-和它的方法,您已经声明spy正在恢复of观测来触发subscribe There's likely a way to use that Router Stub for your purposes ( eg @Yuri's answer ), but your question only asked for a way to test that logic and the isLoading variable.可能有一种方法可以将路由器存根用于您的目的(例如isLoading的回答),但您的问题只要求一种测试该逻辑和isLoading变量的方法。
  • If your router is protected or private (a good practice), you can still spy on it with bracket notation - eg spyOn(component['router'], 'events') .如果您的路由器是protectedprivate (一个很好的做法),您仍然可以使用括号表示法对其进行监视 - 例如spyOn(component['router'], 'events')

You need to create a simple Router stub to allow emitting various router events during the test.您需要创建一个简单的路由器存根以允许在测试期间发出各种路由器事件。

Router stub:路由器存根:

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

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

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

Then you simply use that stub:然后您只需使用该存根:

...
let router: Router;

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

A test looks like this:测试如下所示:

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

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

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

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