我有一个问题,我不知道什么是最佳解决方案。仅出于上下文考虑,我将Typescript用于NodeJS(v12)应用程序,我有一个包装一些库并从Subject(rxjs)发出一些值的类。
想法是,将来我希望对此包装的类进行更改,因此我在顶部构建了一个接口,并使用Subject发出了要由其他类使用的值。
我一直在寻找答案,在我看来,这种用例非常普遍,因此我假设以前有更多人遇到过这个问题,但是我发现的所有答案都与next()的值有关。 )是,因此要对最终触发新数据的某些逻辑的结果进行单元测试。
此用例将涉及单元测试,将一些数据注入到Subject中,然后期望已经调用了多个服务(为此使用sinon)
一些小片段如下:
import {Subject} from 'rxjs';
// This is to fake another library I am using, I will just call a callback on an interval
class SomeCustomLibrary {
generateSomethingToBeWrapped(f: (someDate: Date) => void): void {
setInterval(() => {
f(new Date());
}, 1000);
}
}
import {Subject} from 'rxjs';
interface IWrapper {
someObservable: Subject<any>;
}
class CustomWrapper implements IWrapper {
public someObservable: Subject<any>;
public someLibrary: SomeCustomLibrary;
constructor() {
this.someObservable = new Subject<any>();
this.someLibrary = new SomeCustomLibrary();
this.someLibrary.generateSomethingToBeWrapped(someDate => {
this.someObservable.next(someDate);
});
}
}
class MyVeryImportantBusinessLogicService {
// Making it public to avoid some boilerplate in the test, I am making it private and
// injecting it the real implementation
public myWrappedObservable: IWrapper;
constructor() {
this.myWrappedObservable = new CustomWrapper();
this.myWrappedObservable.someObservable.subscribe(newData => {
this.doSomethingVeryCritical(newData);
});
}
private doSomethingVeryCritical(newData: any) {
// call external class 1
// call external class 2
// call external class 3
console.log('Something has been done at this point');
}
}
describe('Now trying to test my logic', () => {
const myVeryImportantBusinessLogicService = new MyVeryImportantBusinessLogicService();
it('Here I would expect all the external classes (services) to be called', (done) => {
myVeryImportantBusinessLogicService.myWrappedObservable.someObservable.next({hello: 'world'});
setTimeout(() => {
// sinon expect external class 1
// sinon expect external class 2
// sinon expect external class 3
done();
}, 1);
});
});
这种方法有效,但是我担心的是,我不得不强迫引入setTimeout才能达到我的期望,从而使单元测试不得不等待人为地,任意地等待。
这使测试“等待”要完成的事情(因为我嘲笑了所有依赖项,因此会立即发生),但是我认为这不是正确(或最佳)的方法。
我想到的另一种方法是分别测试代码,对于此类,只需确保已预订了特定的预订即可。
这里有什么好的做法可以采用吗?