如何使用Jest测试同一类中的方法调用?

时间:2019-05-14 16:40:04

标签: javascript jestjs

我正在尝试在类中测试函数调用以确保它们被调用,但是我似乎无法弄清楚如何使用Jest进行操作。

自动模拟无效,使用模块工厂参数调用jest.mock也不起作用。

这是有问题的课程,我想测试调用play()是否调用playSoundFile()。

class SoundPlayer {
  constructor() {
    this.foo = 'bar';
  }

  playSoundFile(fileName) {
    console.log('Playing sound file ' + fileName);
  }

  play() {
    this.playSoundFile('song.mp3');
  }
}

module.exports = SoundPlayer;

这是测试文件:

const SoundPlayer = require('../sound-player');
jest.mock('../sound-player');

it('test', () => {
  const soundPlayerConsumer = new SoundPlayer();

  const coolSoundFileName = 'song.mp3';
  soundPlayerConsumer.play();

  const mockPlaySoundFile = SoundPlayer.mock.instances[0].playSoundFile;
  expect(mockPlaySoundFile.mock.calls[0][0]).toEqual(coolSoundFileName);
});

mockPlaySoundFile.mock.calls为空,因此会出错。

2 个答案:

答案 0 :(得分:2)

我建议您不要模拟任何内部方法。相反,您可以模拟任何外部依赖关系并调用应该公开的方法。然后,您针对 public (假定在外部调用)方法返回的内容运行断言,并检查模拟(模拟的外部依赖项)是否被调用。

在此特定示例中,只有console.log

console.log = jest.fn();
const soundPlayerConsumer = new SoundPlayer();
soundPlayerConsumer.play();
expect(console.log).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenCalledWith('Playing sound file song.mp3');

在更现实的情况下,可能需要模拟document甚至使用jsdom来模拟<audio /> HTML元素。但是方法是一样的。

答案 1 :(得分:0)

如果我不嘲笑整个类,而只是监视该函数,它将起作用。但是,这无法解决测试密集功能的问题,例如调用数据库。

const SoundPlayer = require('../sound-player');

it('test', () => {
  const soundPlayerConsumer = new SoundPlayer();
  const playSpy = jest.fn();
  soundPlayerConsumer.playSoundFile = fileName => playSpy(fileName);

  soundPlayerConsumer.play();

  expect(playSpy).toHaveBeenCalledWith('song.mp3');
});