如何使用茉莉间谍为window.location.pathname编写单元测试? [英] How to write unit test for window.location.pathname with jasmine spy?
问题描述
我有angular 8应用程序,并且正在使用OidcSecurityService作为身份服务器.
I have angular 8 application and I am using the OidcSecurityService for identity server.
我正忙于为其编写一些单元测试.但是我陷入了以下代码部分:
And I am bussy to write some unit tests for it. But I am stuck on the following code part:
ngOnInit() {
this.oidcSecurityService
.checkAuth()
.subscribe(isAuthenticated => {
if (!isAuthenticated) {
Eif ('/autologin' !== window.location.pathname) {
this.write('redirect', window.location.pathname);
this.router.navigate(['/autologin']);
}
}
if (isAuthenticated) {
this.navigateToStoredEndpoint();
}
});
//console.log('windowPath', window.location.pathname);
}
和完整的ts文件如下:
and the complete ts file looks like this:
export class AppComponent implements OnInit {
title = 'cityflows-client';
constructor(public oidcSecurityService: OidcSecurityService, public router: Router) {}
ngOnInit() {
this.oidcSecurityService
.checkAuth()
.subscribe(isAuthenticated => {
if (!isAuthenticated) {
if ('/autologin' !== window.location.pathname) {
this.write('redirect', window.location.pathname);
this.router.navigate(['/autologin']);
}
}
if (isAuthenticated) {
this.navigateToStoredEndpoint();
}
});
//console.log('windowPath', window.location.pathname);
}
/**
* Generate new set of access tokens for a http call
*/
refreshSession() {
this.oidcSecurityService.authorize();
}
/**
* Redirect function for redirecting the user to the login page when application starts.
*/
private navigateToStoredEndpoint() {
const path = this.read('redirect');
if (this.router.url === path) {
return;
}
if (path.toString().includes('/unauthorized')) {
this.router.navigate(['/']);
} else {
this.router.navigate([path]);
}
}
/**
*
* @param key
* For checking if user is authenticated for the URL
* And if not will go back to root directory
*/
private read(key: string): any {
const data = localStorage.getItem(key);
if (data != null) {
return JSON.parse(data);
}
return;
}
/**
*
* @param key
* @param value
* for checking if url is the correct one
*/
private write(key: string, value: any): void {
localStorage.setItem(key, JSON.stringify(value));
}
}
我的单元测试如下:
import { CommonModule } from '@angular/common';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { OidcSecurityService } from 'angular-auth-oidc-client';
import { of } from 'rxjs';
import { AppComponent } from './app.component';
import { OidcSecurityServiceStub } from './shared/mocks/oidcSecurityServiceStub';
import { routes } from './app-routing.module';describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let authenticatedService: OidcSecurityServiceStub;
const routerSpy = { navigate: jasmine.createSpy('/autologin') };
const routerNavigateSpy = { navigate: jasmine.createSpy('navigate') };
let router: Router;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
providers: [
{ provide: OidcSecurityService, useClass: OidcSecurityServiceStub },
{ provide: Router, useValue: routerSpy },
{ provide: Router, useValue: routerNavigateSpy }
],
declarations: [AppComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
authenticatedService = new OidcSecurityServiceStub();
fixture.detectChanges();
});
it('should create the app', () => {
expect(component).toBeTruthy();
});
it('Navigate if not authenticated', () => {
spyOn(component.oidcSecurityService, 'checkAuth').and.returnValue(of(false));
component.ngOnInit();
expect(routerSpy.navigate).not.toHaveBeenCalledWith(['/']);
});
it(' Should Navigate if not is root path ', () => {
spyOn(component.oidcSecurityService, 'checkAuth').and.returnValue(of(false));
component.ngOnInit();
expect(routerSpy.navigate).not.toHaveBeenCalledWith('/autologin');
});
});
但是在承保关系中,我在这条线上看到一个E:
But in the coverage rapport I see a E on this line:
if ('/autologin' !== window.location.pathname) {
未采用其他路径.
那我要改变什么?
谢谢
我可以做到:
public href: string = '/';
然后:
ngOnInit() {
this.oidcSecurityService
.checkAuth()
.subscribe(isAuthenticated => {
if (!isAuthenticated) {
if ('/autologin' !== this.href) {
this.write('redirect', this.href);
this.router.navigate(['/autologin']);
}
}
if (isAuthenticated) {
this.navigateToStoredEndpoint();
}
});
}
推荐答案
尝试添加如下内容:
it('should navigate to autologin', () => {
const oldPathName = window.location.pathname;
spyOn(component.oidcSecurityService, 'checkAuth').and.returnValue(of(false));
window.location.pathname = '/somethingElse'; // I am not sure if this will change the URL or not.
// If it changes the URL in the browser, it can be bad.
component.ngOnInit();
expect(routerSpy.navigate).toHaveBeenCalledWith('/autologin');
window.location.pathname = oldPathName; // restore it to the old version
});
您应该使用ActivatedRoute
,而不是使用location.pathname
.然后,您可以在单元测试中轻松模拟它.
Instead of using location.pathname
, you should be using ActivatedRoute
. Then you can mock it easily in your unit tests.
https://angular.io/api/router/ActivatedRoute 如何在Angular 5中使用ActivatedRoute?
或者甚至路由器也可以获取当前URL. 在Angular中获取当前网址
Or maybe even the router to get the current URL. Get current url in Angular
这篇关于如何使用茉莉间谍为window.location.pathname编写单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!