Как смоделировать маршрут Angular 2?

У меня есть следующий код...

export class LoginComponent {
    userName: string;
    password: string;
    rememberMe: boolean = false;
    constructor( private auth: AuthenticationService,
                 private router: Router) {
      ...
    }
    ...
}

Я пытаюсь выполнить модульный тест, но моя первая попытка не удалась....

beforeEach(() => {
        router = new Router();
        component = new LoginComponent(authService, router);
});

Потому что ему нужны параметры для конструктора Router. Здесь я увидел...

beforeEach(() => addProviders([
    APP_ROUTER_PROVIDERS, // must be first
    {provide: APP_BASE_HREF, useValue: '/'}, // must be second
    {provide: ActivatedRoute, useClass: Mock},
    {provide: Router, useClass: Mock}
]));

Но мне кажется, что нигде в моих зависимостях нет APP_ROUTER_PROVIDERS или Mock, поэтому я думаю, что это может быть устаревшим (или мне нужны зависимости).

Как мне издеваться над этим? Это даже не имеет значения для теста, над которым я работаю.


person Jackie    schedule 28.11.2016    source источник


Ответы (3)


Для простого случая вы можете просто создать свой собственный макет и предоставить его по значению, например:

describe('whatever', () => {
  let mockRouter: any;
  ...

  beforeEach(async(() => {
    // create your own mock 
    mockRouter = jasmine.createSpyObj('Router', ['navigate']);

    ...

    TestBed.configureTestingModule({
      declarations: [LoginComponent],
      providers: [
        // provide it by value
        { provide: Router, useValue: mockRouter },
        ...
      ],
    }).compileComponents();
  }));

  ...

}); 

При этом используется внедрение зависимостей испытательного стенда, а не попытка «new-up» тестируемого класса.

Для примера в контексте см., например. один из моих проектов на Гитхаб.

person jonrsharpe    schedule 28.11.2016
comment
Чем это отличается от того, как это делается в реальном проекте (я писал до того, как посмотрел). Вроде там нужны только... TestBed.configureTestingModule({imports: [RouterTestingModule]}); и router = TestBed.get(Router);? Я еще не тестировал его, поэтому я не уверен, что он работает. - person Jackie; 29.11.2016
comment
@Jackie Что ты имеешь в виду под настоящим проектом? - person jonrsharpe; 29.11.2016
comment
@ Джеки, ну, они тестируют сам маршрутизатор, вы тестируете что-то, что его использует. Вы посмотрели на пример, который я связал, и попробовали это? - person jonrsharpe; 29.11.2016
comment
Я постараюсь посмотреть немного больше и посмотреть, получу ли я это. Извините, мне эти вещи кажутся такими эзотерическими. В моем случае меня не волнуют побочные эффекты LOL, но я думаю, вы говорите, что это делает некоторые дополнительные вещи, которые мне не нужны. - person Jackie; 29.11.2016

Вот рабочий пример загрузки параметров строки запроса для каждого теста. Работает на Angular 2.3.

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        MyViewerComponent,
        ...
      ],
      imports: [
        HttpModule,
        FormsModule,
        RouterModule,
        ...  
      ],
      providers: [
        {provide: ActivatedRoute, useValue: {queryParams: {test: 111}}},
        {provide: MyService, useClass: MyMockService}
      ]
    })
      .compileComponents();
  }));
person David Dehghan    schedule 16.01.2017

Я принял приведенный выше ответ, потому что он кажется правильным, однако на самом деле я реализовал его по-другому...

describe("Login Component", () => {
    let component: LoginComponent;
    let authService: AuthenticationService;
    let router: Router;

    describe("Testing the subscription happens", () => {
        beforeEach(() => {
            TestBed.configureTestingModule({imports: [RouterTestingModule]});
            router = TestBed.get(Router);
            authService = new AuthenticationService();
            authService.notifications = new Subject();
            authService.notifications.subscribe = jasmine.createSpy("SpyToTestNotifications");
        });
        it("Make sure we try to subscribe to the auth event", () => {
            component = new LoginComponent(authService, router);
            expect(authService.notifications.subscribe).toHaveBeenCalled();
        })
    });
});

Как видите, для этого требуется всего 2 строки в файле beforeEach...

TestBed.configureTestingModule({imports: [RouterTestingModule]});
router = TestBed.get(Router);

Однако, согласно @jonrsharpe, это делает много вещей, поэтому вы не можете гарантировать, какие другие побочные эффекты могут возникнуть. Но это быстро, это грязно и, похоже, «работает».

person Jackie    schedule 28.11.2016