Typescript 测试驱动开发 TDD (15)
异步测试 (Asynchronous tests)
正如我们在探索JavaScript和TypeScript时所看到的,我们编写的大部分代码都是异步的。这意味着我们无法准确控制回调函数何时被调用,或者Promise何时解析,因为我们正在等待一个超出我们控制范围的事件发生。这经常在单元测试中引起问题,在这种情况下,我们需要等待异步事件完成后才能继续进行测试。以下是一个示例类:
1 class MockAsync { 2 executeSlowFunction( 3 complete: (value: string) => void 4 ) { 5 setTimeout(() => { 6 complete(`competed`); 7 },1000); 8 } 9 }
在这里,我们有一个名为MockAsync的类,它有一个名为executeSlowFunction的方法。该方法接受一个名为complete的回调函数作为唯一参数,并在1秒后调用它。我们可以按照以下方式编写对这个类的测试:
1 describe("failing async tests", () => { 2 it("should wait for callback to complete", () => { 3 let mockAsync = new MockAsync(); 4 console.log(`1. calling executeSlowFunction`); 5 let returnValue !: string; 6 mockAsync.executeSlowFunction((value: string) => { 7 console.log(`2. complete called`); 8 returnedValue = value; 9 }); 10 11 }) 12 });
在这里,我们有一个名为"failing async tests"的测试套件,以及一个名为"should wait for callback to complete"的测试。该测试首先创建了一个名为mockAsync的MockAsync类实例。然后它向控制台输出一条消息,并创建了一个变量named returnedValue来保存调用executeSlowFunction方法时返回的值。接下来,它调用executeSlowValueFunction函数并定义了一个回调函数。这个回调函数向控制台输出一条消息,并将回调返回的值存储在returnedValue变量中。然后,该测试向控制台输出第三条消息,并检查returnedValue变量是否包含字符串值"completed"。
运行此测试,然而,会得到以下的失败输出:
在这里,我们可以看到打印到控制台的消息是"1. calling executeSlowFunction"和"3. checking return value"。我们完全没有收到消息"2. executeSlowFunctionReturned"。我们的测试也失败了,因为返回值变量expectedValue应该是 "completed",但实际上是undefined的。
导致这个测试失败的原因是测试本身没有等待1秒钟,以便executeSlowFunction函数调用完成回调。我们真正需要的是一种信号方式,告诉我们的测试只有在异步调用完成后才执行测试期望值。