【问题标题】:Jest Error: Test ES6 class invocation when calling method开玩笑错误:调用方法时测试 ES6 类调用
【发布时间】:2020-09-03 19:47:19
【问题描述】:

我正在使用 ES6 制作支付库,但我没有太多的单元测试经验,尤其是 Jest。我尝试模拟我的主类使用的两个类,在第一种情况下,我的测试工作正常,但在第二种情况下,即使我在第一种情况下做同样的事情,它也不起作用。

我有以下代码:

import Core from './core/index';
import Providers from './providers/index';

export default class MyLib {
  #keyId = '';
  #access_token = '';
  #core = {};

  constructor(env = 'prod', auth = {}) {
    this.#core = new Core(env, auth);
  }

  getFingerprintId() {
    return this.#core.fingerprintId();
  }

  async tokenize(dataCard) {
    this.#keyId = await this.#core.getKeyId(this.#access_token);
    const provider = new Providers().getInstance();
    return await provider.tokenize(this.#keyId, dataCard);
  }
}

我想测试 Providers 类是否被以下代码调用:

jest.mock('../core/index');
jest.mock('../providers/index');

beforeEach(() => {
    sdk = new MyLib('test', {
      username: '',
      password: '',
      key: ''
      provider: '',
      country: '',
    });
  });

it('The card is tokenized', () => {
    const dataCard = {
      cardNumber: '123456789123',
      cardExpirationMonth: '12',
      cardExpirationYear: '2030',
      cardType: 'visa',
    };
    sdk.tokenize(dataCard);
    expect(Providers).toHaveBeenCalled();
  });

但是当我运行测试时出现以下错误:

● Making test to MyLib › The card is tokenized

    expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 1
    Received number of calls:    0

      31 |     };
      32 |     sdk.tokenize(dataCard);
    > 33 |     expect(Providers).toHaveBeenCalled();
         |                       ^
      34 |   });
      35 | });
      36 |

      at Object.it (src/__tests__/index.spec.js:33:23)

测试大约需要 6 秒,然后中断,这是为什么呢?

【问题讨论】:

  • 在您发布的代码中,Providers 不是间谍,但报告表明它是。请发布所有相关代码。很可能是以错误的方式发现的。
  • 对不起。那部分代码我没有复制,我已经更新了。
  • 间谍不应该在它被断言的时候被调用。测试应该是async,它应该是await sdk.tokenize(dataCard)。由于类具有复杂的结构,我希望自动模拟在某些时候会失败。如果是这种情况,请考虑手动模拟它们。
  • 我进行了修复,但仍然无法模拟 Provider 类和对应于以下行的“tokenize”方法:return await provider.tokenize(this.#KeyId, dataCard);

标签: javascript ecmascript-6 jestjs es6-modules


【解决方案1】:

Providers 类的结构不够简单,无法通过自动模拟正确处理。它返回的对象层次结构应该手动模拟:

let mockTokenize = jest.fn();

let mockGetInstance = jest.fn() => (
    { tokenize: mockTokenize };
);

jest.mock('../providers/index', () => (
  {
    default: jest.fn(() => (
      { getInstance: mockGetInstance }
    ))
  }
});

测试应该是异步的,并且在断言之前使用链式承诺:

  it('The card is tokenized', async () => {
    ...
    mockTokenize.mockResolvedValue('whatever');
    await expect(await sdk.tokenize(dataCard)).resolves.toBe('whatever');
    expect(mockTokenize).toHaveBeenCalledWith(...);
    // redundant assertions
    expect(Providers).toHaveBeenCalled();
    expect(mockGetInstance).toHaveBeenCalled();
  });

【讨论】:

  • 感谢您的帮助。我仍然有问题,我认为这是因为我的经验不足,你能帮我看看这个要点吗?我添加了你给我的代码。 gist.github.com/luenmuvel/96e3bf9e820e2ab098bc5447855932af
  • 错误说明了这是什么意思,注意:这是防止未初始化的模拟变量的预防措施。如果确保延迟需要模拟,则允许以mock(不区分大小写)为前缀的变量名。保证这些方法模拟不会在导入时调用,因此可以安全地按照帖子的建议进行操作,更新了。
  • 非常感谢您的帮助,我已经解决了这个错误,但现在我要解决另一个外星错误,我会认为您的解决方案有效,我会提出另一个问题。再次非常感谢您。
猜你喜欢
  • 2019-12-19
  • 2020-08-16
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 2018-06-03
  • 2018-07-30
  • 2023-02-23
相关资源
最近更新 更多