Подтвердить что ты не робот

Угловой 2/4/6/7 - модульное тестирование с маршрутизатором

В Angular 2.0.0 я тестирую компонент, использующий Router. Однако я получаю, что "Поставляемые параметры не соответствуют какой-либо сигнатуре целевого вызова". ошибка. В Visual Studio код в spec.ts это новый Router(), который выделен красным цветом

Я очень ценю, если кто-то может сообщить мне, какой будет правильный синтаксис? Заранее спасибо. Мой код выглядит следующим образом:

spec.ts

import { TestBed, async } from '@angular/core/testing';
import { NavToolComponent } from './nav-tool.component';
import { ComponentComm } from '../../shared/component-comm.service';
import { Router } from '@angular/router';

describe('Component: NavTool', () => {
  it('should create an instance', () => {
    let component = new NavToolComponent( new ComponentComm(), new Router());
    expect(component).toBeTruthy();
  });
});

Конструктор компонентов

constructor(private componentComm: ComponentComm, private router: Router) {}
4b9b3361

Ответ 1

Вы также можете просто использовать RouterTestingModule и просто включить функцию навигации следующим образом...

import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { Router } from '@angular/router';

import { MyModule } from './my-module';
import { MyComponent } from './my-component';

describe('something', () => {

    let fixture: ComponentFixture<LandingComponent>;
    let router: Router;

    beforeEach(() => {

        TestBed.configureTestingModule({
            imports: [
                MyModule,
                RouterTestingModule.withRoutes([]),
            ],
        }).compileComponents();

        fixture = TestBed.createComponent(MyComponent);
        router = TestBed.get(Router);

    });

    it('should navigate', () => {
        const component = fixture.componentInstance;
        const navigateSpy = spyOn(router, 'navigate');

        component.goSomewhere();
        expect(navigateSpy).toHaveBeenCalledWith(['/expectedUrl']);
    });
});

Ответ 2

Это потому, что у Route есть некоторые зависимости, которые он ожидает передать своему конструктору.

Если вы используете компоненты Angular, вам не следует пытаться проводить отдельные тесты. Вы должны использовать инфраструктуру тестирования Angular для подготовки среды тестирования. Это означает, что Angular может создать компонент, внедрить все необходимые зависимости вместо того, чтобы пытаться создать все.

Чтобы начать, у вас должно быть что-то вроде

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

describe('Component: NavTool', () => {
  let mockRouter = {
    navigate: jasmine.createSpy('navigate')
  };
  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ NavToolComponent ],
      providers: [
        { provide: Router, useValue: mockRouter },
        ComponentComm
      ]
    });
  });
  it('should click link', () => {
    let fixture = TestBed.createComponent(NavToolComponent);
    fixture.detectChanges();
    let component: NavToolComponent = fixture.componentInstance;
    component.clickLink('home');
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/home']);
  });
});

Или что-то типа того. Вы используете TestBed для настройки модуля с нуля для тестирования. Вы настраиваете его почти таким же образом с @NgModule.

Здесь мы просто издеваемся над роутером. Поскольку мы всего лишь модульное тестирование, нам может не потребоваться реальная возможность маршрутизации. Мы просто хотим убедиться, что он вызывается с правильными аргументами. Шутка и шпион смогут поймать этот призыв для нас.

Если вы хотите использовать реальный маршрутизатор, то вам нужно использовать RouterTestingModule, где вы можете настроить маршруты. Смотрите пример здесь и здесь

Смотрите также:

Ответ 3

Жасмин становится лучше с полными шпионскими объектами...

describe(..., () => {
    const router = jasmine.createSpyObj('Router', ['navigate]);
    ...
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            providers: [  { provide: Router, useValue: router } ],
            ...
    });        
});

Ответ 4

Вот пример, если мы добавим сервис Route в наш контроллер компонентов:

import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing'; // Because we inject service in our component
import { Router } from '@angular/router'; // Just if we need to test Route Service functionality

import { AppComponent } from './app.component';
import { DummyLoginLayoutComponent } from '../../../testing/mock.components.spec'; // Because we inject service in your component

describe('AppComponent', () => {
  let router: Router; // Just if we need to test Route Service functionality

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        AppComponent,
        DummyLoginLayoutComponent // Because we inject service in our component
      ],
      imports: [
        RouterTestingModule.withRoutes([
          { path: 'login', component: DummyLoginLayoutComponent },
        ]) // Because we inject service in our component
      ],
    }).compileComponents();

    router = TestBed.get(Router); // Just if we need to test Route Service functionality
    router.initialNavigation(); // Just if we need to test Route Service functionality
  }));

  it('should create the app', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.debugElement.componentInstance;
    expect(app).toBeTruthy();
  }));
});

Мы также можем протестировать другие функционалы, такие как navigate(). Так, на всякий случай:

it('should call eventPage once with /register path if event is instanceof NavigationStart', fakeAsync(() => {
    spyOn(analyticService, 'eventPage');
    router.navigate(['register'])
      .then(() => {
        const baseUrl = window.location.origin;
        const url = '${baseUrl}/register';
        expect(analyticService.eventPage).toHaveBeenCalledTimes(1);
        expect(analyticService.eventPage).toHaveBeenCalledWith(url);
      });
}));

Мой файл со всеми фиктивными компонентами (mock.components.specs.ts)

import { Component } from '@angular/core';

@Component({
    selector: 'home',
    template: '<div>Dummy home component</div>',
    styleUrls: []
})

export class DummyHomeComponent { }