单元测试queryParams订阅(Angular5)

时间:2018-05-24 12:39:37

标签: javascript angular unit-testing karma-jasmine

我在测试ActivatedRoute queryParams订阅中的逻辑时遇到问题。

constructor(private router: Router, private route: ActivatedRoute, private auth: AuthService) {}

ngOnInit(): void {
  this.route.queryParams.subscribe((params:any) => {
    if(params['data']) {
      this.handle(params['data']);
    } else {
      if (this.auth.isAuthenticated()) {
        this.router.navigate(['/home']);
      }
    }
  });
}

我想测试一下:

  • 如果在提供模拟this.handle()时触发了params['data']
  • 如果没有参数且this.auth.isAuthenticated()返回true this.router.navigate被称为

我尝试了很多事情,但我的想法已经不多了。

我的测试文件:

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

  const mockService = {
    navigate: jasmine.createSpy('navigate'),
    isAuthenticated: jasmine.createSpy('isAuthenticated'),
    queryParams: jasmine.createSpy('queryParams')
  };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [TestComponent],
      providers: [
        { provide: Router, useValue: mockService },
        { provide: ActivatedRoute, useValue: mockService },
        { provide: AuthService, useValue: mockService }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(TestComponent);
    component = fixture.componentInstance;

    mockService.navigate.calls.reset();
  }));

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

  it('should navigate away when authenticated', () => {
    mockService.isAuthenticated.and.returnValue(true);
    mockService.queryParams.and.callFake((data, params) => new Observable(o => o.next({ params: {} })));
    component.ngOnInit();
    expect(mockService.navigate).toHaveBeenCalledWith(['/home']);
  });
});

但是我得到了TypeError: this.route.queryParams.subscribe is not a function。我知道mockService.isAuthenticated.and.returnValue(true);工作正常,因为在使用params订阅之前,我在ngOnInit()内只有if语句。

我试图将mockService更改为:

const mockService = {
  navigate: jasmine.createSpy('navigate'),
  isAuthenticated: jasmine.createSpy('isAuthenticated'),
  queryParams: {
    subscribe: jasmine.create('subscribe')
  }
};

我也尝试过:

const mockService = {
  navigate: jasmine.createSpy('navigate'),
  isAuthenticated: jasmine.createSpy('isAuthenticated'),
  queryParams: {
    subscribe: Observable.of({ params: {} })
  }
};

但没有成功,对于最后两个我得到Expected spy navigate to have been called with [ [ '/home' ] ] but it was never called.

那么有人知道如何在querParams订阅中正确测试逻辑吗?

2 个答案:

答案 0 :(得分:4)

我不能说现在回答是否为时已晚,但这也许会对新的Google员工有所帮助...

我设法通过以下方式解决该问题:

		class ActivatedRouteMock {
			queryParams = new Observable(observer => {
        const urlParams = {
          param1: 'some',
          param2: 'params'
        }
				observer.next(urlParams);
				observer.complete();
			});
		}

		beforeEach(async(() => {
			TestBed.configureTestingModule({
				imports: [
					HttpClientTestingModule
				],
				providers: [
					HttpClient,
					HttpHandler,
					ControlContainer,
					{
						provide: ActivatedRoute,
						useClass: ActivatedRouteMock
					}
				]
			}).compileComponents();

			injector = getTestBed();
			httpMock = injector.get(HttpTestingController);
		}));

这使您可以在.subscribe(() => {})方法中声明逻辑。.

希望它会帮助

答案 1 :(得分:1)

您可以在useValue中使用可观察的rxjs对其进行模拟。

const router = {
  navigate: jasmine.createSpy('navigate')
};
beforeEach(async(() => {    
TestBed.configureTestingModule({
  imports: [
    RouterTestingModule.withRoutes([]),
    RouterTestingModule,
    PlanPrimengModule
  ],
  declarations: [YourComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  providers: [
    provideMockStore(),
    {
      provide: ActivatedRoute,
      useValue: {
        queryParams: of({
          param1: "value1",
          param1: "value2"
        })
      }
    },
    { provide: Router, useValue: router }
  ]
}).compileComponents();   }));