开发者问题收集

jest.js 和 useValue 存根在提供程序中无法在角度中工作

2022-03-27
1758

我有一个具有简单 GET 方法的服务:

export class MyService {
  constructor(private http: HttpClient) {}

  getUsers() {
    const path = 'https://gorest.co.in/public/v2/users'

    return this.http.get(path)
  }
}

接下来,我将其注入到一个组件中:

export class AppComponent implements OnInit {
  users: any[]

  constructor(private _myService: MyService) {}

  ngOnInit() {
    this._myService.getUsers().subscribe((usersRes) => {
      this.users = usersRes
    })
  }
}

我还有一个简单的用户存根:

const usersMock = [
  {
    gender: 'female',
    id: 3971,
    name: 'Piotreczi Krawaczi',
  },
]

const myServiceStub = jest.fn().mockImplementation(() => ({
  getUsers: jest.fn().mockReturnValue(of(usersMock))
})

...然后我想在 app.components.spec.ts 中的 TestBed 中使用它。

beforeEach(waitForAsync(() => {
  TestBed.configureTestingModule({
    imports: [HttpClientTestingModule],
    declarations: [AppComponent],
    providers: [{ MyService, useValue: myServiceStub }],
  }).compileComponents()

  fixture = TestBed.createComponent(AppComponent)
  component = fixture.componentInstance
}))

...最后我想测试一下,用户不为空:

it('should get Users', fakeAsync(() => {
  fixture.detectChanges()
  expect(component.users.length).toBeGreaterThan(0)
  flush()
}))

我收到错误: TypeError:无法读取未定义的属性“length” ,这与 expect(component.todos.length).toBeGreaterThan(0) 有关。有人知道为什么 todos 没有更新,并且 getUsers().subscribe 中的代码没有执行吗?

我也尝试过 useClass 而不是 useValue ,其中: providers: [{ MyServiceService, useClass: MyServiceStubClass }], 和:

class MyServiceStubClass {
  getTodos() {
    return of(todosMock)
  }

  getUsers() {
    return of(usersMock)
  }
}

...但是它不起作用。

2个回答

我认为您可能需要在 expect 之前 tick 以使 subscribe 生效。

试试这个:

class MyServiceStubClass {
  getTodos() {
    return of(todosMock)
  }

  getUsers() {
    return of(usersMock)
  }
}

providers: [{ MyService, useClass: MyServiceStubClass }],
....

it('should get Users', fakeAsync(() => {
  // first fixture.detectChanges() calls ngOnInit
  fixture.detectChanges();
  // tick should wait for the subscribe to be completed before going to expect
  tick();
  expect(component.users.length).toBeGreaterThan(0);
  flush();
}))
AliF50
2022-03-28

我有解决方案。我必须使用:

@Injectable()
class MockMyService extends MyService {
  override getUsers() {
    return of(usersMock)
  }

  override getTodos() {
    return of(todosMock)
  }
}

并在 TestBed.configureTestingModule 中使用:

providers: [{provide: MyService, useClass: MockMyService}],
Kamczatka
2022-03-31