简体   繁体   English

尝试在 Jest 中模拟 setInterval(),使用 jest.useFakeTimers(),未按预期工作,断言导致类型匹配器错误

[英]Attempting to mock setInterval() in Jest, using jest.useFakeTimers(),not working as expected and assertions result in type matcher errors

I've read all the posts on here and Jest documentation as well, but I seem to be still doing something wrong.我已经阅读了此处的所有帖子和 Jest 文档,但我似乎仍然做错了什么。 Im writing unit tests for a service which is using a global setInterval() function. When I write the test, I keep getting the following error:我正在为使用全局 setInterval() function 的服务编写单元测试。当我编写测试时,我不断收到以下错误:

expect(received).toHaveBeenCalledTimes(expected)

    Matcher error: received value must be a mock or spy function

    Received has type:  function
    Received has value: [Function anonymous]

      40 |
      41 |     expect(smartlook).toHaveBeenCalledTimes(2);
    > 42 |     expect(setInterval).toHaveBeenCalledTimes(1);
         |                         ^
      43 |   });
      44 | });

Here is the function:这是 function:

/**
 * trackSmartlook
 */
function trackSmartlook( eventType: string, eventName: string, properties = false ): void {
  if (window.smartlook) {
    window.smartlook.apply([eventType, eventName, properties]);
  } else {
    const checkSmartlookLoaded = setInterval(() => {
      if (window.smartlook) {
        window.smartlook.apply([eventType, eventName, properties]);
        clearInterval(checkSmartlookLoaded);
      }
    }, 1000);
  }
}

export default trackSmartlook;

And here is the test file:这是测试文件:

import trackSmartlook from 'Services/app/SmartlookService';

const eventType      = 'track';
const eventName      = 'event name';

/**
 * Mocking window.smartlook
 */
Object.defineProperty(window, 'smartlook', {
  value   : jest.fn().mockImplementation(),
});

beforeEach(() => {
  jest.useFakeTimers();
});

afterEach(() => {
  jest.runOnlyPendingTimers();
  jest.useRealTimers();
});

/**
 * Test SmartlookService
 */
describe('test SmartlookService', () => {
  it ('trackSmartlook calls setInterval and call window.smartlook twice', () => {
    const smartlook = jest.spyOn(window,'smartlook').mockImplementation();
    smartlook.mockReturnValue(undefined);

    trackSmartlook(eventName, eventType);

    jest.advanceTimersByTime(1001);

    expect(smartlook).toHaveBeenCalledTimes(2);
    expect(setInterval).toHaveBeenCalledTimes(1);
  });
});

Ive tried everything that is suggested in Jest documentation.我尝试了 Jest 文档中建议的所有内容。 Ie jest.spyOn(global,'setInterval'), jest.useFakeTimers('legacy') etc, but still i'm getting the same outcome.即 jest.spyOn(global,'setInterval'), jest.useFakeTimers('legacy') 等,但我仍然得到相同的结果。 Any suggestions would be appreciated.任何建议,将不胜感激。 Jest version 27.0.1开玩笑版本 27.0.1

尝试使用jest.useFakeTimers('legacy')

I have this example, maybe help you.我有这个例子,也许对你有帮助。 Using jest version 27.5.1 ("jest": "^27.5.1").使用玩笑版本 27.5.1(“玩笑”:“^27.5.1”)。

import { shallowMount } from "@vue/test-utils";
import ProgressBar from '../ProgressBar.vue'

describe('ProgressBar.vue', () => {
  // Function to run before each test.
  beforeEach(() => {
    jest.useFakeTimers('legacy') // Replaces global timer functions. legacy to works setInterval return value mocks.
  })
  
  test('clears timer when finish is called', () => {
    jest.spyOn(window, 'clearInterval') // Spies on the clearInterval function.
    
    setInterval.mockReturnValue(123) // Configures setInterval to return 123.

    const wrapper = shallowMount(ProgressBar)
    wrapper.vm.start() // Calls start to start the timer.
    wrapper.vm.finish() // Calls clearInterval function.

    // Asserts that the clearInterval mock was called with the value returned from setInterval.
    expect(window.clearInterval).toHaveBeenCalledWith(123)
  })
})

ProgressBar.vue:进度条.vue:

<template>
  <div
    :class="{hidden: hidden}"
    :style="{width: percent + '%'}"
  >

  </div>
</template>

<script>
export default {
  data() {
    return {
      hidden: true,
      percent: 0
    }
  },
  methods: {
    start() {
      this.percent = 0
      this.hidden = false

      this.timer = setInterval(() => {
        this.percent++
      }, 100)
    },
    finish() {
      this.hidden = true
      this.percent = 100

      clearInterval(this.timer)
    }
  }
}
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM