【问题标题】:Unit test for remote call at ngOnInt在 ngOnInit 进行远程调用的单元测试
【发布时间】:2019-11-13 06:48:03
【问题描述】:

这是我的组件:

 export class MyComponent implements OnInit {

    me: User;  
    let userServiceGetMeSpy; 

    constructor(private userService: UserService) {

    }

    ngOnInit() {


        this.userService.getMe().subscribe(user => {

          this.me = user;

在 ngOnit 的组件开始时,我正在调用一个服务来执行远程调用并获取用户对象,然后我将返回的对象设置为组件的“我”属性。

我的目标是编写一个单元测试来检查在从ngOnit方法成功调用UserService的getMe方法后是否设置了me属性。

我可以考虑一下这个规范代码:

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let userService: UserService;
  let mockedUser = new User();

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    userService = TestBed.get(UserService);


    mockedUser.Name = "Admin User";

    userServiceGetMeSpy = spyOn(userService, "getMe").and.callFake(() => {
      return of<User>(mockedUser)
    })

    fixture.detectChanges();
  });

我对编写单元测试感到困惑:

  it('should set "me" property on calling getMe at ngOnit on MyComponent', () => {

    //What to write here?

  });

我可以想到一个测试来检测是否调用了 getMe 方法

  it('should have called user service get me on page load', () => {

    component.ngOnInit();
    fixture.detectChanges();
    expect(userServiceGetMeSpy).toHaveBeenCalled();
  });

我需要进一步检查在调用之后是否调用了“me”属性。

【问题讨论】:

  • 单元测试不应该检查服务器,因此你可以模拟返回的数据并在你的组件中检查它
  • 我已经嘲笑过了。我在我的问题中提到过: userServiceGetMeSpy = spyOn(userService, "getMe").and.callFake(() => { return of(mockedUser) })
  • expect(component.me).toBe(mockedUser);?
  • getMe 不是静态方法,而是返回 observable 的远程调用。我应该在哪里订阅 getme?

标签: angular typescript unit-testing karma-jasmine


【解决方案1】:

首先,从 MyComponent 类中删除 userServiceGetMeSpy。您唯一需要的是在调用组件的ngOnInit 之前模拟服务调用UserService.getMe

spyOn(userService, 'getMe').and.returnValue(of(user));

请注意,fixture.detectChanges 会触发组件的更改检测周期并隐式调用其ngOnInit 方法。因此,无需在您的测试中再次显式调用ngOnInit

您可以按如下方式编写测试。

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  const user = new User();
  let userService: UserService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ MyComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    userService = TestBed.get(UserService);
    spyOn(userService, 'getMe').and.returnValue(of(user));
    fixture.detectChanges();
  });

  it('should have called user service get me on page load', () => {
    expect(userService.getMe).toHaveBeenCalledTimes(1);
    expect(component.me).toBe(user);
  });
});

【讨论】:

  • getMe 正在返回 observable。如何确保getMe已经返回response,才能确认me是否被设置。如果我错了,请纠正我?
  • userService.getMe 模拟使用of 以同步方式传递用户。 expect(component.me).toBe(user); 确认 me 已设置。
猜你喜欢
  • 1970-01-01
  • 2020-12-14
  • 2020-08-08
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 2016-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多