2016-12-16 534 views
2

我有一個組件,當用戶登錄它時,路由到一個名爲/dashboard的網址我真的很努力弄清楚爲什麼我得到以下錯誤。角度2測試w /路由器

cannot read property 'args' of undefined 

我一直在關注與路由器測試官方文檔這裏https://angular.io/docs/ts/latest/guide/testing.html#!#routed-component 找到,但它似乎沒有幫助。我的一半問題是我不太理解文檔中的所有代碼。這裏是我的路線單元測試

beforeEach(async(()=>{ 

     class AuthStub{ 
     private loggedin: boolean = false; 
      login(){ 
       return this.loggedin = true; 

      } 
     }; 

     class RouterStub{ 
     navigateByUrl(url:string){return url;} 
     } 

    TestBed.configureTestingModule({ 
     declarations: [ HomePageContentComponent ], 
     providers:[ 
     {provide: Auth, useClass:AuthStub}, 
     {provide: Router, useClass: RouterStub} 
     ] 
    }) 
    .compileComponents() 
    })); 

    beforeEach(()=>{ 

     fixture = TestBed.createComponent(HomePageContentComponent); 
     comp = fixture.componentInstance; 

     de = fixture.debugElement.query(By.css('.loginbtn')); 
     el = de.nativeElement; 
     fixture.detectChanges(); 

    }); 

    it('Should log in and navigate to dashboard', inject([Router],(router:Router)=>{ 

     const spy = spyOn(router, 'navigateByUrl'); 

     el.click(); 

     const navArgs = spy.calls.first().args[0]; 

     expect(navArgs).toBe('/dashboard'); 

    }))  
}); 

所以我的問題是什麼是這行代碼做...

const navArgs = spy.calls.first().args[0]; 

和我怎麼能解決我的問題?

服務添加

@Injectable() 
export class Auth { 
    lock = new Auth0Lock('fakefakefakefakefake', 'fake.auth0.com', { 
     additionalSignUpFields: [{ 
      name: "address",        
      placeholder: "enter your address" 
     }], 
     theme: { 
      primaryColor:"#b3b3b3", 
     }, 
     languageDictionary: { 
      title: "FAKE" 
     } 
    }); 

    userProfile: any; 

    constructor(private router: Router) { 
     this.userProfile = JSON.parse(localStorage.getItem('profile')); 

     this.lock.on("authenticated", (authResult) => { 
      localStorage.setItem('id_token', authResult.idToken); 

      this.lock.getProfile(authResult.idToken, (error, profile) => { 
       if (error) { 

        alert(error); 
        return; 
       } 

       profile.user_metadata = profile.user_metadata || {}; 
       localStorage.setItem('profile', JSON.stringify(profile)); 
       this.userProfile = profile; 
      }); 
      this.router.navigate(['/dashboard']); 
     }); 
    } 

    public login(){ 
     this.lock.show(); 

    }; 

    public authenticated() { 
     return tokenNotExpired(); 
    }; 

    public logout() { 
     localStorage.removeItem('id_token'); 
     localStorage.removeItem('profile'); 
     this.router.navigate(['/logout']); 
    }; 
} 
+0

@yurzui將我的服務添加到問題 – Bean0341

回答

3

比方說,你有以下組件:

{ provide: Router, useClass: RouterStub } 

裏面你:

@Component({ 
    selector: 'home-comp', 
    template: `<button (click)="login()" class="loginbtn">Login</button> 
    ` 
}) 
export class HomePageContentComponent { 
    constructor(private auth: Auth, private router: Router) { } 

    login() { 
    this.router.navigateByUrl(`/dashboard`); 
    } 
} 

在您的測試與嘲笑版本替換真實Router後案例:

it('Should log in and navigate to dashboard', inject([Router],(router:Router)=>{ 

router將爲RouterStub的實例。

那麼你窺探的navigateByUrl方法來看着它被調用多少次

const spy = spyOn(router, 'navigateByUrl'); 

,所以當你在.loginbtn按鈕router.navigateByUrl運行點擊(見上成分)和spy incrementes calls一些信息(例如,什麼是所謂的說法)

最後,在這條線

const navArgs = spy.calls.first().args[0]; 

預計您的router.navigateByUrl方法被調用至少一次,然後從第一個調用獲得傳遞參數。

這裏工作Live Example

可能你出了問題的地方,不執行你的router.navigateByUrl

+0

作爲對此答案的迴應,對於我的情況,我的導航是從身份驗證服務確認後的構造函數中觸發的。所以我實際上想要爲服務構建此導航測試,而不是調用服務的組件? – Bean0341

+0

Auth服務的當前模擬不包括調用router.navigateByUrl。你能分享你的真實服務嗎? – yurzui

+0

添加了我的服務 – Bean0341