我有一个服务返回由 ngrx 选择器公开的值。 组件定义此服务以获取数据。 我正在使用服务的模拟为组件编写单元测试,我需要模拟服务为每个单元测试返回不同的值。 我怎样才能做到这一点?
组件
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
providers: [TestService],
})
export class TestComponent {
test$ = this.testService.test$;
test: number;
constructor(private service: TestService) {
service.test$.subscribe(test => this.test = test);
}
}
服务
export class TestService {
test$ = this.store.select(getTestValueFromStore);
constructor(private store: Store<any>){}
}
尝试 1(重置服务的值):不起作用
class MockTestService {
**test$ = of(10);**
}
describe('TestComponent', () => {
let testService: TestService;
beforeEach((() => {
// Define component service
TestBed.overrideComponent(
TestComponent,
{ set: { providers: [{ provide: TestService, useClass: MockTestService }] } }
);
TestBed.configureTestingModule({
declarations: [TestComponent]
})
.compileComponents();
}));
beforeEach(async() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
testService = fixture.debugElement.injector.get(TestService);
fixture.detectChanges();
});
it('should do something when the value returned by the service is 20', fakeAsync(() => {
**testService.test$ = of(20);**
tick();
expect(component.test).toEqual(20);
}));
});
尝试 2:使用主题。 karma 抛出错误 “‘next’属性在‘Observable’类型上不存在” 因为 TestService 返回可观察对象,而不是主题
class MockTestService {
**test$ = new BehaviourSubject(10);**
}
describe('TestComponent', () => {
let testService: TestService;
beforeEach((() => {
// Define component service
TestBed.overrideComponent(
TestComponent,
{ set: { providers: [{ provide: TestService, useClass: MockTestService }] } }
);
TestBed.configureTestingModule({
declarations: [TestComponent]
})
.compileComponents();
}));
beforeEach(async() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
testService = fixture.debugElement.injector.get(TestService);
fixture.detectChanges();
});
it('should do something when the value returned by the service is 20', fakeAsync(() => {
**testService.test$.next(20);**
tick();
expect(component.test).toEqual(20);
}));
});
最佳答案
您在问题中说过您希望“模拟服务为每个单元测试返回不同的值”。为此,您将不得不对组件的定义方式进行一些更改。
最重要的变化是将订阅移至 ngOnInit() 并移出组件的构造函数。如果您这样做,那么您可以控制订阅何时触发,否则它将在创建组件时触发,从而很难为每个单元测试返回不同的值。
完成后,您需要小心调用
fixture.detectChanges()
的地方。这是因为这将执行ngOnInit()
,这将执行订阅并将 Observable 返回的值存储到component.test
中。请注意,由于您使用的是of()
,因此它只会发出一次然后完成。如果您将新值放入testService.test$
,它不会再次发出。设置完成后,您可以在调用 fixture.detectChanges 之前更改
testService.test$
的值,并根据需要设置值。
我已经设置了一个 StackBlitz为了证明这一点,尽可能少地更改代码以使其正常工作。有两个测试,每个测试返回不同的值。
希望对您有所帮助!
关于angular - 更改模拟服务为 Angular/Jasmine/Redux 中的每个测试返回的可观察值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54176001/