jest.js 提供者的 useValue 存根在 angular 中不工作

jest.js and useValue stub for provider not working in angular

我有一个使用简单 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: Cannot read property 'length' of undefined,这与 expect(component.todos.length).toBeGreaterThan(0) 有关。有人知道为什么 todos 没有更新并且 getUsers().subscribe 中的代码没有被执行吗?

我也 useClass insead useValue 尝试过: providers: [{ MyServiceService, useClass: MyServiceStubClass }], 和:

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

  getUsers() {
    return of(usersMock)
  }
}

...但它不起作用。

我认为您可能需要 tick 才能使 subscribeexpect 之前生效。

试试这个:

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();
}))

我有办法。我必须使用:

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

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

并在 TestBed.configureTestingModule 中:

providers: [{provide: MyService, useClass: MockMyService}],