JS策略模式实现中Jest报this.stragtegy.doOperation方法错误
报错根因定位
报错是两类问题叠加导致的,其中直接触发错误的原因是接口不匹配:
- 核心方法名完全不匹配:
Calculation类的doOperation方法内部,尝试调用当前绑定策略实例的doOperation方法,但两个策略类(CalculationStrategy、CalculationStrategyB)对外实现的方法名是doAction,实例上不存在doOperation方法,自然会抛出this.strategy.doOperation is not a function的错误。 - 拼写不一致导致的逻辑失效:全链路代码中对策略属性的拼写存在错误(错拼为
stragtegy,正确拼写为strategy):Calculation类的构造函数中初始化的实例属性是错拼的this.stragtegy- 类中定义的setter访问器键名是正确的
strategy(只有给实例的strategy属性赋值时才会触发setter逻辑) - 测试用例中直接给实例的错拼属性
stragtegy赋值,完全没有触发预先定义的setter逻辑,虽然碰巧同名能拿到值,但设计逻辑已经完全走偏
- 策略模式核心约定缺失:所有策略类没有遵循统一接口的要求,方法名自定义,和上下文类的调用逻辑没有对齐。
代码调整方案
按照策略模式的规范逐文件修改即可,核心是统一方法名、修正拼写、打通赋值逻辑:
1. 调整Calculation.js
修正所有错拼的属性名,保证内部引用一致:
class Calculation { constructor(a, b, op) { this.a = a; this.b = b; this.op = op; // 修正拼写 this.strategy = null; } static Create(a, b, op){ return new Calculation(a, b, op); } GetResults() { return this.op(this.a, this.b) } addOperationToName(fn){ return function(name){ const operation = name + ' is an operation'; return fn(operation); } } sayOperation(name){ return name; } obtainStructor(){ return this.a +' '+ this.b; } // 修正setter的参数和赋值逻辑 set strategy(strategyInstance){ this.strategy = strategyInstance; } doOperation(){ // 修正属性引用,调用策略实例的统一方法 return this.strategy.doOperation(); } } module.exports = Calculation;
2. 调整CalculationStrategy.js
把方法名对齐上下文的调用要求,保证接口统一:
class CalculationStrategy{ // 方法名从doAction改为doOperation doOperation(){ return 'This is Calculation Strategy 1'; } } module.exports = CalculationStrategy;
3. 调整CalculationStrategyB.js
同样对齐统一的方法名要求:
class CalculationStrategyB{ // 方法名从doAction改为doOperation doOperation(){ return 'This is Calculation Strategy 2'; } } module.exports = CalculationStrategyB;
4. 调整测试用例CalculationStrategy.test.js
修正赋值时的属性名,保证赋值逻辑能正确触发setter,把策略实例绑定到实例属性上:
const calculation = require('../src/models/Calculation'); const calculationStrategy = require('../src/CalculationStrategy'); const calculationStrategyB = require('../src/CalculationStrategyB'); const Product = require('../src/Operations/Product'); test('Test Strategy of Calculation', () => { let op = Product; let customCalculation = new calculation(1,2, op); const strategy = new calculationStrategy(); const strategyB = new calculationStrategyB(); // 修正属性名,从错拼的stragtegy改为正确的strategy customCalculation.strategy = strategy; expect(customCalculation.doOperation()).toBe('This is Calculation Strategy 1'); customCalculation.strategy = strategyB; expect(customCalculation.doOperation()).toBe('This is Calculation Strategy 2'); });
修改完成后,Jest测试即可正常运行,完全符合策略模式的核心逻辑:上下文类负责持有策略实例、委托策略执行具体逻辑,所有策略类实现统一接口,可以灵活替换且不需要修改上下文代码。
内容的提问来源于stack exchange,提问作者BeefNoodle
相关产品推荐
相关产品推荐

