我想让使用 Jasmine 和 Marbles 更轻松地为我的应用程序效果创建测试。
为此,我想创建几个函数以在每个测试中导入,以减少代码重复并提高测试的可读性。
所以让我们假设我有这三个文件:
效果文件
@Injectable()
export class CustomEffects {
customEffect$ = createEffect(() => {
this.actions$.pipe(
ofType(customActions.customAction),
map(action => customActions.otherAction({name: 'name'}))
)
});
constructor(private actions$: Actions) {}
}
测试文件
describe('CustomEffects', () => {
let effects: CustomEffects;
let actions: Observable<Action>;
beforeEach(() => {
TestBed.configureTestingModule(effectsTestingMOduleConfiguration(
CustomEffects,
provideMockActions(() => actions)
));
actions = TestBed.inject(Actions);
effects = TestBed.inject(CustomEffects);
});
afterEach(() => {
TestBed.resetTestingModule();
});
it('effect customEffect$ should return otherAction', () => {
const inputAction = customActions.customAction();
const expectedActions = [
customActions.otherAction({name: 'name'})
];
testEffect(actions, effects, 'customEffect$', inputAction, expectedActions);
});
});
函数文件
export function effectsTestingMOduleConfiguration(effects: any, ...apiService: any) {
const providers = [effects];
if(apiService) {
providers.push(apiService);
}
return {providers}
}
export function testEffect<T>(actions: Observable<Action>, effects: T, effectName: keyof T, inputAction: Action, expectedActions: Action[]) {
const actionMarbles: {[marble: string]: Action};
const firstLetter = 'b'.charCodeAt(0);
const letters = expectedActions.map((_, index) => String.fromCharCode(firstLetter + index));
const marbles = '-(' + letters.reduce((prev, curr) => prev + curr, '') + ')';
letters.forEach(letter => actionMarbles[letter] = expectedActions[letter.charCodeAt(0) - firstLetter]);
actions = hot('-a', {a: inputAction});
const expectedResult = cold(marbles, actionMarbles);
expect(effects[effectName]).toBeObservable(expectedResult);
}
对我来说,这看起来应该可以正常工作,但是测试失败并显示以下消息:
Expected: -(b),
Received: ,
Expected: [{
"frame": 10,
"notification": {
"kind": "N",
"value": {
"name": "name",
"type": "[CustomActions] Custom Action"
},
"hasValue": true
}
}]
Received: []
但是,如果我像这样更改我的测试文件:
describe('CustomEffects', () => {
let effects: CustomEffects;
let actions: Observable<Action>;
beforeEach(() => {
TestBed.configureTestingModule(effectsTestingMOduleConfiguration(
CustomEffects,
provideMockActions(() => actions)
));
actions = TestBed.inject(Actions);
effects = TestBed.inject(CustomEffects);
});
afterEach(() => {
TestBed.resetTestingModule();
});
it('effect customEffect$ should return otherAction', () => {
const inputAction = customActions.customAction();
const expectedActions = [
customActions.otherAction({name: 'name'})
];
actions = hot('-a', {a: inputAction});
const expectedResult = cold('-(b)', {b: expectedActions[0]});
expect(effects['customEffect$']).toBeObservable(expectedResult);
});
});
或者像这样:
describe('CustomEffects', () => {
let effects: CustomEffects;
let actions: Observable<Action>;
beforeEach(() => {
TestBed.configureTestingModule(effectsTestingMOduleConfiguration(
CustomEffects,
provideMockActions(() => actions)
));
actions = TestBed.inject(Actions);
effects = TestBed.inject(CustomEffects);
});
afterEach(() => {
TestBed.resetTestingModule();
});
it('effect customEffect$ should return otherAction', () => {
const inputAction = customActions.customAction();
const expectedActions = [
customActions.otherAction({name: 'name'})
];
testEffect(effects, 'customEffect$', inputAction, expectedActions);
});
function testEffect<T>(effects: T, effectName: keyof T, inputAction: Action, expectedActions: Action[]) {
const actionMarbles: {[marble: string]: Action};
const firstLetter = 'b'.charCodeAt(0);
const letters = expectedActions.map((_, index) => String.fromCharCode(firstLetter + index));
const marbles = '-(' + letters.reduce((prev, curr) => prev + curr, '') + ')';
letters.forEach(letter => actionMarbles[letter] = expectedActions[letter.charCodeAt(0) - firstLetter]);
actions = hot('-a', {a: inputAction});
const expectedResult = cold(marbles, actionMarbles);
expect(effects[effectName]).toBeObservable(expectedResult);
}
});
测试现在将毫无问题地通过。
所以我想做的是让函数testEffect正常工作,如果可能的话,改变函数effectsTestingMOduleConfiguration这样就不需要手动传递provideMockActions(() => actions)了。