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

如何用Jasmine监视localStorage方法?解决测试报错问题

Why the Error Occurs

The error Error: <toHaveBeenCalled> : Expected a spy, but got Function. happens because of how older Firefox versions handle the localStorage object:

  • In Firefox 45.9.0, the methods of localStorage (like getItem) are non-configurable and non-writable native functions.
  • Jasmine's spyOn works by replacing the target method with a spy function. But if the original method can't be modified (due to non-configurable/writable flags), the spy never actually replaces the native getItem method.
  • When your test runs expect(localStorage.getItem).toHaveBeenCalled(), it's checking the original native function—not the spy you tried to create. Jasmine throws the error because only spies have the toHaveBeenCalled() matcher.
How to Fix It

The most reliable fix is to mock the entire localStorage object instead of trying to spy on the native one. This isolates your test from the real browser storage and avoids issues with non-configurable methods.

Solution: Mock LocalStorage

Here's how to rewrite your test with a mock:

it('should return true when someKey is "true"', function() {
  // Save the original localStorage to restore later
  const originalLocalStorage = window.localStorage;

  // Create a mock localStorage with spy methods
  const mockLocalStorage = {
    getItem: jasmine.createSpy('getItem').and.returnValue('true'),
    removeItem: jasmine.createSpy('removeItem')
  };

  // Replace the global localStorage with our mock
  window.localStorage = mockLocalStorage;

  try {
    const returnValue = modifiesLocalStorage();

    // Verify the spies were called correctly
    expect(mockLocalStorage.getItem).toHaveBeenCalledWith('someKey');
    expect(mockLocalStorage.removeItem).toHaveBeenCalledWith('someKey');
    expect(returnValue).toBeTruthy();
  } finally {
    // Restore the original localStorage to avoid breaking other tests
    window.localStorage = originalLocalStorage;
  }
});

Alternative: Make the Method Configurable (Less Preferred)

If you prefer to use the real localStorage (not recommended for test isolation), you can redefine the getItem method to be configurable before spying on it:

it('should return true when someKey is "true"', function() {
  // Override the property descriptor to make getItem configurable/writable
  Object.defineProperty(localStorage, 'getItem', {
    configurable: true,
    writable: true
  });

  // Now spyOn will work as expected
  spyOn(localStorage, 'getItem').and.returnValue('true');
  spyOn(localStorage, 'removeItem');

  const returnValue = modifiesLocalStorage();

  expect(localStorage.getItem).toHaveBeenCalledWith('someKey');
  expect(localStorage.removeItem).toHaveBeenCalledWith('someKey');
  expect(returnValue).toBeTruthy();
});

Note: This approach might have unintended side effects on other tests or the real localStorage, so the mock method is always safer.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:57:45