You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jasmine+Karma测试时SpyOn报'B无setter/不可写'错误的解决咨询

Fixing "B is not declared writable or has no setter" in Jasmine Tests for Rollup-Compiled Code

Let's break down why you're hitting this error and walk through the fixes step by step.

Why the Error Happens

Your test has two key issues:

  1. B isn't exported: In your original code, you only export A, so mainFunctions doesn't contain a B property at all. Trying to spy on a non-existent property is invalid.
  2. Const exports are non-writable: Even if you did export B with const, ES module exports declared with const are read-only by default. Jasmine's spyOn needs to replace the function, which fails on non-writable properties.

The cleanest way to make your functions testable is to encapsulate them in an object. Object properties are writable by default, so Jasmine can spy on them without extra work.

Update Your Main Code (main.js)

export const appFunctions = {
  B: () => { console.log("B is called"); },
  A: () => { appFunctions.B(); }
};

Write the Test (test.js)

import { appFunctions } from './main.js';

describe('When calling function A', function() {
  beforeEach(() => {
    // Spy on B and mock its implementation (use .callThrough() if you want to keep the original behavior)
    spyOn(appFunctions, 'B').and.stub();
    // Call the function we're testing
    appFunctions.A();
  });

  it('should invoke function B', function() {
    expect(appFunctions.B).toHaveBeenCalled();
  });
});

Solution 2: Export B and Make It Writable

If you prefer to keep individual function exports, you can export B explicitly and modify its writability before spying on it.

Update Your Main Code (main.js)

export const B = () => { console.log("B is called"); };
export const A = () => { B(); };

Write the Test (test.js)

import * as mainFunctions from './main.js';

describe('When calling function A', function() {
  beforeEach(() => {
    // Make B writable so Jasmine can replace it with a spy
    Object.defineProperty(mainFunctions, 'B', { writable: true });
    // Set up the spy
    spyOn(mainFunctions, 'B');
    // Call A
    mainFunctions.A();
  });

  it('should invoke function B', function() {
    expect(mainFunctions.B).toHaveBeenCalled();
  });
});

Why This Works

  • Object encapsulation: By putting A and B in an object, we avoid the read-only restriction of const exports, making it easy for Jasmine to spy on B.
  • Writable export adjustment: When using individual exports, Object.defineProperty overrides the read-only setting, allowing Jasmine to replace B with a spy function.

内容的提问来源于stack exchange,提问作者dilusha_dasanayaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 07:57:46