首页 > 解决方案 > 在 Angular 中逐个测试地覆盖提供程序

问题描述

在基于每个测试测试 Ngrx 效果时,我想覆盖服务提供者以涵盖成功和失败响应。

到目前为止,我尝试的是在 TestBed 中提供我的服务:

describe('Account Effects', () => {

  let actions: ReplaySubject<any>;
  let effects: AccountEffects;
  let store: Store<IAccountsState>;

  const email = 'someone@gmail.com';
  const password = 'abc123!';

  beforeEach(async () => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
      ],
      providers: [
        AccountEffects,
        provideMockActions(() => actions),
        provideMockStore<IAccountsState>({ initialState }),
        {
          provide: AccountsService,
          useValue: { _signIn: () => of(null) }
        }
      ]
    });

   store = TestBed.get(Store);
  });


  beforeEach(async () => {
    effects = TestBed.get(AccountEffects);
  });
});

然后在每个测试中,覆盖提供者:

describe('signIn$ success', () => {
  beforeEach(() => {
    TestBed.overrideProvider(AccountsService, {
      useValue: {
        _signIn: () => of({ authenticated: true })
      }
    });
  });
    
  it('should dispatch signInSuccess when a successful response is received', () => {
    actions = new ReplaySubject(1);
    actions.next(AccountActions.signIn({ email, password }));
    
    effects.signIn$.subscribe(result => {
      expect(result).toEqual(AccountActions.signInSuccess({ email }));
    });
  });
});

我遇到的问题是在测试中,accountService._signIn它不是一个函数:

afterAll TypeError 中抛出了一个错误:

this.accountsService._signIn 不是函数

我需要能够覆盖每个测试用例中返回的值。

我一直在关注:

https://indepth.dev/testing-and-faking-angular-dependencies/

我究竟做错了什么?

标签: angularunit-testing

解决方案


我认为你应该改变 AccountsService 的模拟。Account 服务是一个类,你正在模拟一个函数。您应该如下更改规格

class  AccountsServiceMock {
    _signIn(){
       of(null)
    }
}

TestBed.configureTestingModule({
  imports: [
    RouterTestingModule,
  ],
  providers: [
    AccountEffects,
    provideMockActions(() => actions),
    provideMockStore<IAccountsState>({ initialState }),
    {
      provide: AccountsService,
      useClass: AccountsServiceMock 
    }
  ]
});

如果您想更改每个 spec 中 signin 的返回值,您可以 spyOn 它并设置返回值。希望这能完成这项工作。


推荐阅读