如何使用Jasmine测试包含异步方法的Person类代码?
如何用Jasmine测试Person类的异步getName方法
首先得说个关键点:你当前的getName方法其实有个小问题——它用了setTimeout但没有对外暴露异步操作的结果,内部的return根本传不到外部调用的地方,所以首先得重构这个方法,让它能把结果传递出来,常用的两种方式是返回Promise或者接受回调参数,下面分别讲这两种情况的测试方法:
1. 先重构getName为Promise风格(推荐)
先修改你的Person类,让getName返回一个Promise,这样就能用Jasmine的异步测试特性来处理:
class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return `${this.firstName} ${this.lastName}`; // 这里加个空格更符合全名的格式~ } getName() { // 返回Promise,在setTimeout完成后resolve结果 return new Promise((resolve) => { setTimeout(() => { resolve(this.getFullName()); }, 100); }); } } module.exports = Person;
对应的测试方案
Jasmine处理异步测试有几种简洁的方式:
方式一:使用done回调
这是Jasmine早期常用的异步测试方式,通过调用done()告诉框架异步操作已经完成:
const Person = require('./index'); describe('Test Person methods', () => { let programmer; beforeEach(() => { programmer = new Person('John', 'Gray'); }); it('should return the correct full name asynchronously', (done) => { programmer.getName().then((fullName) => { expect(fullName).toBe('John Gray'); done(); // 必须调用这个,否则Jasmine会认为测试超时 }); }); });
方式二:使用async/await(更简洁)
现代JS里用async/await写异步测试可读性更高,Jasmine完全支持这种写法:
it('should return the correct full name using async/await', async () => { const fullName = await programmer.getName(); expect(fullName).toBe('John Gray'); });
如果要Spy方法(比如验证getFullName被调用)
如果你想测试getName是否真的调用了getFullName,可以用Jasmine的spyOn:
it('should call getFullName when getName is invoked', async () => { // 先spy getFullName,并且让它执行原方法 spyOn(programmer, 'getFullName').and.callThrough(); await programmer.getName(); // 验证getFullName被调用了一次 expect(programmer.getFullName).toHaveBeenCalledTimes(1); });
2. 用回调风格改造getName(不推荐,但兼容旧写法)
如果你不想用Promise,也可以让getName接受一个回调参数来传递结果:
getName(callback) { setTimeout(() => { callback(this.getFullName()); }, 100); }
对应的测试代码
同样用done回调来处理:
it('should return full name via callback', (done) => { programmer.getName((fullName) => { expect(fullName).toBe('John Gray'); done(); }); });
为什么原方法无法测试?
你原来的getName方法里,setTimeout内部的return是无效的——因为setTimeout的回调函数是异步执行的,外部调用programmer.getName()根本拿不到这个返回值,所以必须通过Promise或回调把异步结果暴露出来,才能被测试捕获。
内容的提问来源于stack exchange,提问作者darKnight
相关产品推荐
相关产品推荐

