Angular Jasmine单元测试中为何测试用例执行顺序偶尔异常?
问题描述
我正在学习Angular测试,遇到了奇怪的问题:完全相同的代码下,执行ng test时,有时subtract测试用例(it块)会在add测试用例之前执行,但预期add应该先执行(有时又能正常按顺序执行)。关闭VS Code集成终端后重新执行ng test,有时又能恢复正常顺序。
另外补充:this.logger.log的输出在ng test中不显示,这是另一个问题。
测试代码
import { CalculatorService } from './calculator.service'; describe ('calculatorService',()=>{ let calculator:CalculatorService; let loggerSpy:any; beforeEach(()=>{ console.log ("calling the beforeEach"); loggerSpy=jasmine.createSpyObj('LoggerServiceSpy', ['log']); calculator= new CalculatorService(loggerSpy); }); it('should add two numbers', ()=>{ let result=calculator.add(2,2); console.log ("add test"); expect(result).toBe(4); expect(loggerSpy.log).toHaveBeenCalledTimes(1); }); it('should substract two numbers', ()=>{ let result=calculator.subtract(2,2); console.log ("substract test"); expect(result).toBe(0, "unexpected substracion result"); expect(loggerSpy.log).toHaveBeenCalledTimes(1); }); });
CalculatorService代码
import {Injectable} from '@angular/core'; import {LoggerService} from './logger.service'; @Injectable({ providedIn: 'root' }) export class CalculatorService { constructor(private logger: LoggerService) { } add(n1: number, n2:number) { this.logger.log("Addition operation called"); return n1 + n2; } subtract(n1: number, n2:number) { this.logger.log("Subtraction operation called"); return n1 - n2; } }
LoggerService代码
import {Injectable} from '@angular/core'; @Injectable({ providedIn: 'root' }) export class LoggerService { log(message:string) { console.log(message); } }
问题原因与解决方案
测试用例执行顺序不稳定的原因
- Karma的watch模式特性:默认
ng test会启动watch模式,Karma在该模式下可能会根据文件变化重新执行部分测试,或启用并行执行逻辑,导致测试用例顺序不固定。 - Jasmine的随机执行策略:Jasmine默认会随机打乱测试用例的执行顺序,目的是强制开发者保证测试用例的独立性(你的代码已经通过
beforeEach在每个测试前重新初始化实例,所以顺序不影响测试结果,仅日志输出顺序变化)。
解决方法
- 如果需要强制固定执行顺序,可在项目根目录的
karma.conf.js中添加配置:
或临时执行命令时添加参数:module.exports = function(config) { config.set({ // 其他配置... client: { jasmine: { random: false // 关闭随机执行 } } }); };ng test --no-random - 更推荐无需纠结顺序,因为你的测试用例已完全独立(每个
it块都通过beforeEach重新创建calculator和loggerSpy),无论顺序如何,测试结果都是可靠的。
logger.log无输出的解决方法
测试中用jasmine.createSpyObj创建的间谍对象,默认只会记录调用情况,不会执行原方法逻辑。若要保留原log方法的console.log输出,可修改beforeEach中的间谍创建逻辑:
beforeEach(()=>{ console.log ("calling the beforeEach"); // 先创建真实的LoggerService实例 const realLogger = new LoggerService(); // 创建间谍并指定调用原方法 loggerSpy = jasmine.createSpyObj('LoggerServiceSpy', ['log']); loggerSpy.log.and.callThrough(); // 让间谍调用原方法 calculator= new CalculatorService(loggerSpy); });
内容的提问来源于stack exchange,提问作者user6791921
相关产品推荐
相关产品推荐

