我有一个用于反应形式的异步验证器,该反应器在模糊时调度一个动作。此操作将触发一个效果,该效果将按摩来自服务的某些数据。
在验证器中,我使用选择器来监听商店,并使用rxjs运算符以所需的形式获取数据。这运作良好。但是,我一直在此功能的测试范围内。为什么我的测试不能涵盖整个操作?
用户名验证器
export const UniqueUsernameValidator = (store) => {
return (control: any): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
console.log(store)
store.dispatch(new CheckUsername(control.value));
return store.pipe(select(selectUsernameIsUnique)).pipe(
take(2),
tap((val) => console.log(val)),
filter(isUnique => isUnique !== undefined),
map(isUnique => isUnique ? null : {usernameIsNotUnique: true}),
)
}
}
用户名验证器规范
describe('UniqueUsernameValidator', () => {
const storeMock = {
dispatch() {
return true
},
pipe() {
return of(true);
}
};
let control = {
value: 'abc123'
}
it('should dispatch an action of CheckUsername', () => {
UniqueUsernameValidator(storeMock)(control.value)
})
})
TLDR:为什么它缺少此覆盖范围,这是模拟商店的正确方法吗?
答案 0 :(得分:1)
您将返回一个在测试中从未订阅的可观察对象。订阅
中的逻辑是订阅返回的observable的行为。.pipe(
take(2),
tap((val) => console.log(val)),
filter(isUnique => isUnique !== undefined),
map(isUnique => isUnique ? null : {usernameIsNotUnique: true}),
)
您需要测试返回的observable的发射值。
let validationResult;
const sub = UniqueUsernameValidator(storeMock)(control.value).subscribe(result => {
validationResult = result;
});
sub.unsubscribe();
expect(validationResult.usernameIsNotUnique).toEqual(true);
看到您知道可观察对象是由其创建的,可以像这样将其解包,但是如果可观察对象是异步的,则需要进行异步测试。
我使用此辅助函数来异步测试可观察对象。
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export async function firstEmitted<T>(obs$: Observable<T>): Promise<T> {
return new Promise<T>(resolve => {
const finalise = new Subject<void>();
obs$.pipe(takeUntil(finalise)).subscribe(value => {
finalise.next();
resolve(value);
});
});
}
并像使用它
it('should dispatch an action of CheckUsername', async(async () => {
const validationResult = await firstEmitted(UniqueUsernameValidator(storeMock)(control.value));
expect(validationResult.usernameIsNotUnique).toEqual(true);
}));
The
async(async () =>
使某些人感到困惑,但是第一个异步是来自角度测试模块的异步函数,它声明测试函数是anync函数,而第二个异步函数则将该函数标记为异步,就像我们在函数中使用await运算符一样。 / p>