Angular 4单元测试 - 无法读取属性' root'未定义的

时间:2017-05-29 08:22:33

标签: angular unit-testing angular-ui-router angular2-routing

我的单元测试有问题。我不知道这个测试有什么问题。我搜索了一些消息,但没有什么对我有用。当我想模拟路由器时,我有一个错误TypeError: Cannot read property 'root' of undefined。 感谢您提供任何帮助。

错误:

 TypeError: Cannot read property 'root' of undefined
        at rootRoute (webpack:///~/@angular/router/@angular/router.es5.js:5880:0 <- src/test.ts:53760:30)
        at DynamicTestModuleInjector.get (ng:///DynamicTestModule/module.ngfactory.js:401:75)
        at DynamicTestModuleInjector.getInternal (ng:///DynamicTestModule/module.ngfactory.js:919:55)
        at DynamicTestModuleInjector.NgModuleInjector.get (webpack:///~/@angular/core/@angular/core.es5.js:3556:25 <- src/test.ts:3909:44)
        at resolveDep (webpack:///~/@angular/core/@angular/core.es5.js:11017:0 <- src/test.ts:11370:45)
        at createClass (webpack:///~/@angular/core/@angular/core.es5.js:10881:0 <- src/test.ts:11234:32)
        at createDirectiveInstance (webpack:///~/@angular/core/@angular/core.es5.js:10701:21 <- src/test.ts:11054:37)
        at createViewNodes (webpack:///~/@angular/core/@angular/core.es5.js:12064:33 <- src/test.ts:12417:49)
        at createRootView (webpack:///~/@angular/core/@angular/core.es5.js:11969:0 <- src/test.ts:12322:5)
        at callWithDebugContext (webpack:///~/@angular/core/@angular/core.es5.js:13184:25 <- src/test.ts:13537:42)
        at Object.debugCreateRootView [as createRootView] (webpack:///~/@angular/core/@angular/core.es5.js:12644:0 <- src/test.ts:12997:12)
        at ComponentFactory_.create (webpack:///~/@angular/core/@angular/core.es5.js:9890:25 <- src/test.ts:10243:46)
        at initComponent (webpack:///~/@angular/core/@angular/core/testing.es5.js:800:0 <- src/test.ts:55130:49)
        at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:365:0 <- src/test.ts:151874:26)
        at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- src/test.ts:118466:39)
        at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:364:0 <- src/test.ts:151873:32)
    TypeError: Cannot read property 'form' of undefined
        at updateForm (webpack:///src/app/auth/login/login.component.spec.ts:62:14 <- src/test.ts:64296:18)
        at Object.<anonymous> (webpack:///src/app/auth/login/login.component.spec.ts:88:4 <- src/test.ts:64316:9)
        at Object.<anonymous> (webpack:///~/@angular/core/@angular/core/testing.es5.js:336:0 <- src/test.ts:54666:26)
        at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:365:0 <- src/test.ts:151874:26)
        at ProxyZoneSpec.onInvoke (webpack:///~/zone.js/dist/proxy.js:79:0 <- src/test.ts:118466:39)
        at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:364:0 <- src/test.ts:151873:32)
        at Zone.run (webpack:///~/zone.js/dist/zone.js:125:0 <- src/test.ts:151634:43)
        at Object.<anonymous> (webpack:///~/zone.js/dist/jasmine-patch.js:104:0 <- src/test.ts:118180:34)
        at webpack:///~/@angular/core/@angular/core/testing.es5.js:96:0 <- src/test.ts:54426:17
        at ZoneDelegate.invoke (webpack:///~/zone.js/dist/zone.js:365:0 <- src/test.ts:151874:26)
        at AsyncTestZoneSpec.onInvoke (webpack:///~/zone.js/dist/async-test.js:49:0 <- src/test.ts:117775:39)

测试方法:

onSubmit(): void {
const payload = this.form.value;
this.form.reset();
this.form.disable();

this.authService.login(payload)
  .finally(() => {
    this.form.enable();
  })
  .subscribe(
    ({ res }) => {
      if (typeof res.cmp === 'undefined' || typeof res.rel === 'undefined') {
        this.router.navigate(['test']);
      } else {
        this.router.navigate([this.returnUrl]);
      }
    },
    ({ sts }) => {
      this.dialogService.alert({
        title: 'Error',
        message: `${backendMessage(sts, false)}`
      });
    }
  );

}

单元测试:

const mockUser = {
  email: 'test@test.test',
  password: 'Test1235',
  remember: true
};

const mockInvalidUser = {
  email: null,
  password: null,
  remember: true
};

@Injectable()
class AuthServiceMock {

  login(payload: any): Observable<BackendResponse<Auth>> {
    let sessionObj: BackendResponse<Auth> = { sts: null, res: { cmp: null, rel: null, prs: null } };
    return Observable.of(sessionObj);
  }
}

const router = {
  navigate: jasmine.createSpy('navigate')
};

describe('LoginComponent', () => {
  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [AuthModule, AppModule],
      providers: [
        ExtendedFormBuilder,
        { provide: AuthService, useClass: AuthServiceMock },
        { provide: Router, useValue: router }
      ],
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  function updateForm(userEmail: string, userPassword: string): void {
    component.form.controls['prs.email'].setValue(userEmail);
    component.form.controls['prs.passwd'].setValue(userPassword);
  }

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('return url should have a default value', () => {
    expect(component.returnUrl).toBeTruthy();
  });

  it('check form controls values after update', fakeAsync(() => {
    updateForm(mockUser.email, mockUser.password);
    expect(component.form.controls['prs.email'].value).toEqual(mockUser.email);
    expect(component.form.controls['prs.passwd'].value).toEqual(mockUser.password);
  }));

  it('check if the form is valid after set incorrect values', fakeAsync(() => {
    updateForm(mockInvalidUser.email, mockInvalidUser.password);
    expect(component.form.valid).toBeFalsy();
  }));

  fit('should update model on submit', fakeAsync(() => {
    updateForm(mockUser.email, mockUser.password);
    component.onSubmit();
    expect(router.navigate).toHaveBeenCalledWith(['./']);
  }));
});

1 个答案:

答案 0 :(得分:1)

我可能会弄错,但看起来你并没有对实际模板本身做任何事情。因此,最简单的方法是从'@ angular / core'导入NO_ERROR_SCHEMA,并在测试平台配置中提供

providers: [...],
schemas: [NO_ERROR_SCHEMA]

现在,如果/当你想要测试模板,那么你还有一些选择。您可以提供一些路由器存根,如angular test project中所示。他们在测试文件夹下。使用它们并将它们放入testbed声明中,这应至少解决路由问题。您也可以创建自己的存根。或者,您可以配置RouterTestingModule.withRoutes([])。

希望这会有所帮助。