【发布时间】:2019-09-08 06:50:33
【问题描述】:
我正在尝试为 Angular 中的服务编写单元测试。 我想模拟 ngrx 的 store.select 函数,所以我可以测试一个服务如何对商店选择器返回的不同值做出反应。我希望能够单独模拟每个选择器。
我的主要问题是如何模拟参数化选择器。
我之前使用了一个映射到 select 函数的 BehaviourSubject,但这不允许您为不同的选择器返回不同的值。它不可读,因为您在模拟什么选择器并不明显。
选项 1:使用主题的模拟存储:无法知道主题对应于哪个选择器,无法为不同的选择器返回不同的值。
// service.spec.ts
const selectSubject = new BehaviourSubject(null);
class MockStore {
select = () => selectSubject;
}
opt 2:模拟存储使用开关:适用于不同的选择器,但在选择器具有参数时无法使其工作。
// service.spec.ts
// This works well but how can I make it work with selectors with parameters??
const firstSubject = new BehaviourSubject(null);
const secondSubject = new BehaviourSubject(null);
class MockStore {
select = (selector) => {
switch (selector): {
case FirstSelector: {
return firstSubject;
}
case SecondSelector: {
return secondSubject;
}
}
};
}
describe('TestService', () => {
let service: TestService;
let store: Store<any>;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
TestService,
{ provide: Store, useClass: MockStore }
],
});
service = TestBed.get(TestService);
store = TestBed.get(Store);
});
it('should do X when first selector returns A and second selector returns B', () => {
firstSelectorSubject.next(A);
secondSelectorSubject.next(B);
// Write expectation
});
});
我想模拟带有参数化选择器的服务方法,所以我可以用不同的 id 值测试 getUserName
getUserName(id: string): Observable<string> {
return this.store.select(getUser(id)).pipe(
filter(user => user !== null),
map(user => user.fullName)
);
}
【问题讨论】:
-
您可以将商店包装在服务中,如本文所述stackoverflow.com/questions/49288024/…
-
谢谢,但我不认为将选择器包装在服务中以便我可以测试它们是最好的方法。在我看来,Ngrx 已经提供了必要的抽象。
标签: angular unit-testing rxjs store ngrx