使用Jest模拟Angular服务的getter以在组件中使用

6yjfywim  于 2023-05-21  发布在  Jest
关注(0)|答案(1)|浏览(120)

我正在为一个有两个注入服务的Angular组件编写测试。其中一个服务-UpdateService有一个行为主题(属性),它是用默认/初始值设置的-

stateSubj: BehaviorSubject<DefaultState> = new BehaviorSubject<DefaultState>(initialState);

然后,服务有一个getter,它获取此行为主体的value属性-

get state(): DefaultState {
    return this.stateSubj.value;
  }

而setter只接受一组新的属性,并使用行为主体以.next()发出新旧属性。
在我正在测试的组件中,ngOnInit()方法通过getter读取服务的默认状态。

ngOnInit() {
  // some code
  const state = this.updateService.state; // this is undefined

问题是-因为我在测试文件(spec.ts)的最开始就模拟了UpdateService-

jest.mock('../update.service');
describe('MyComponent', () => {
 // tests here

看起来我的组件本身的第一个基本测试失败了

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

控制台中报告的错误是state未定义。当我在控制台上将updateService记录到我的组件的ngOnInit()中时,它返回了服务的所有函数/方法的模拟版本,但其中没有getter,这就是为什么this.updateService.state返回undefined的原因。
我已经尝试了各种方法来设置state属性在我的测试beforeEach(),但没有任何工作-

mockService = jest.mocked(TestBed.inject(UpdateService)); 

// this complains that property 'state' does not exist
jest.spyOn(mockService, 'state', 'get').mockReturnValue(initialState); 

// while any of the below just don't have any effect
mockService.setState(initialState);
mockService.stateSubj = new BehaviorSubject<DefaultState>(initialState);

我做错了什么?

z31licg0

z31licg01#

我对jest没有太多的经验,但我会做以下事情:

// !! Create a fake class that has the properties of update service you need
class MockUpdateService {
  stateSubj = new BehaviorSubject({});
  get state() {
    return this.stateSubj.value; 
  }
  set state(value: any) {
    this.stateSubj.next(value);
  }
}

beforeEach(waitForAsync(() => {
  TestBed.configureTestingModule({
     ...
     // Provide the fake for the real update service
     providers: [{ provide: UpdateService, useClass: MockUpdateService }]
  }).compileComponents();
}));

相关问题