如何测试是否在 NgRX 中调度了动作?
How to test if action is dispatched in NgRX?
我有一个在构造函数中分派操作的组件:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
constructor(store: Store<State>) {
store.dispatch(action1());
store.dispatch(action2());
}
}
我需要测试 action1 和 action2 是否被调度。我正在尝试使用 MockStore 来做到这一点:
import {MockStore, provideMockStore} from '@ngrx/store/testing';
let store: MockStore;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers: [
provideMockStore({ initialState }),
],
}).compileComponents();
store = TestBed.inject(MockStore);
});
这是我的测试:
it('should dispatch an action1 in constructor', () => {
TestBed.createComponent(AppComponent);
const expected = cold('a', {a: action1()});
expect(store.scannedActions$).toBeObservable(expected);
});
it('should dispatch an action2 in constructor', () => {
TestBed.createComponent(AppComponent);
const expected = cold('a', {a: action2()});
expect(store.scannedActions$).toBeObservable(expected);
});
这很奇怪,但只有一项测试通过了。这取决于 dispatch() 调用的顺序。
store.scannedActions$ 只包含一个值。如果组件代码是:
constructor(store: Store<State>) {
store.dispatch(action1());
store.dispatch(action2());
}
那么 store.scannedActions$ 只包含 action2()
如果组件代码是:
constructor(store: Store<State>) {
store.dispatch(action2());
store.dispatch(action1());
}
那么 store.scannedActions$ 只包含 action1()
如何测试这两个动作?
看起来 scannedActions$
尽管它是复数(动作),但只存储了最后一个调度的动作,查看它的 interface。
我只会使用 spyOn
并监视 store.dispatch
并查看是否使用正确的操作调用它。
import {MockStore, provideMockStore} from '@ngrx/store/testing';
let store: MockStore;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers: [
provideMockStore({ initialState }),
],
}).compileComponents();
store = TestBed.inject(MockStore);
});
it('should dispatch action1 and action 2 in constructor', () => {
const dispatchSpy = spyOn(store, 'dispatch').and.callThrough(); // spy on the store
// dispatch but still call the actual implementation
TestBed.createComponent(AppComponent);
fixture.detectChanges(); // used to call ngOnInit, maybe it is not needed
expect(dispatchSpy).toHaveBeenCalledWith(action1());
expect(dispatchSpy).toHaveBeenCalledWith(action2());
});
我有一个在构造函数中分派操作的组件:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
})
export class AppComponent {
constructor(store: Store<State>) {
store.dispatch(action1());
store.dispatch(action2());
}
}
我需要测试 action1 和 action2 是否被调度。我正在尝试使用 MockStore 来做到这一点:
import {MockStore, provideMockStore} from '@ngrx/store/testing';
let store: MockStore;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers: [
provideMockStore({ initialState }),
],
}).compileComponents();
store = TestBed.inject(MockStore);
});
这是我的测试:
it('should dispatch an action1 in constructor', () => {
TestBed.createComponent(AppComponent);
const expected = cold('a', {a: action1()});
expect(store.scannedActions$).toBeObservable(expected);
});
it('should dispatch an action2 in constructor', () => {
TestBed.createComponent(AppComponent);
const expected = cold('a', {a: action2()});
expect(store.scannedActions$).toBeObservable(expected);
});
这很奇怪,但只有一项测试通过了。这取决于 dispatch() 调用的顺序。
store.scannedActions$ 只包含一个值。如果组件代码是:
constructor(store: Store<State>) {
store.dispatch(action1());
store.dispatch(action2());
}
那么 store.scannedActions$ 只包含 action2()
如果组件代码是:
constructor(store: Store<State>) {
store.dispatch(action2());
store.dispatch(action1());
}
那么 store.scannedActions$ 只包含 action1()
如何测试这两个动作?
看起来 scannedActions$
尽管它是复数(动作),但只存储了最后一个调度的动作,查看它的 interface。
我只会使用 spyOn
并监视 store.dispatch
并查看是否使用正确的操作调用它。
import {MockStore, provideMockStore} from '@ngrx/store/testing';
let store: MockStore;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers: [
provideMockStore({ initialState }),
],
}).compileComponents();
store = TestBed.inject(MockStore);
});
it('should dispatch action1 and action 2 in constructor', () => {
const dispatchSpy = spyOn(store, 'dispatch').and.callThrough(); // spy on the store
// dispatch but still call the actual implementation
TestBed.createComponent(AppComponent);
fixture.detectChanges(); // used to call ngOnInit, maybe it is not needed
expect(dispatchSpy).toHaveBeenCalledWith(action1());
expect(dispatchSpy).toHaveBeenCalledWith(action2());
});