如何在笑话中测试从构造函数调用的 init() 函数,然后调用其他异步函数

use*_*459 2 unit-testing async-await jestjs es6-class

我在 JavaScript 中有以下代码:

class SampleClass {
  constructor(param1) {
    this.param1 = param1;
    this.init();
  }
  async init() {
    await this.getData();
    this.loadIframe();
  }
  async getData() {
    const response = fetch(url);
    const data = response.json();
    //set the response to class variable
    this.param2 = data;
  }
  loadIframe() {
    //some logic to load iframe.
  }
}
Run Code Online (Sandbox Code Playgroud)

使用笑话测试此功能的最佳方法是什么?

目前我正在通过模拟 init() 函数来测试构造函数逻辑。

我还必须测试 getData()函数。测试 getData() 方法的方法应该是什么?

我尝试通过不模拟 init() 函数并使用异步测试来测试 getData() 函数,但我不确定 在测试中在哪里使用等待,因为该函数是嵌套的,并从从构造函数调用的 init 中调用。

it('should fetch data', async()=>{
   //some logic  
})
Run Code Online (Sandbox Code Playgroud)

sli*_*wp2 6

您可以使用jest.spyOn(object, methodName)来模拟SampleClass. 我的测试环境是node,所以我模拟对象fetch上的方法global。如果您的测试环境是browser,则该fetch方法位于window对象上。

\n\n

例如

\n\n

sampleClass.js:

\n\n
class SampleClass {\n  constructor(param1) {\n    this.param1 = param1;\n    this.init();\n  }\n  async init() {\n    await this.getData();\n    this.loadIframe();\n  }\n  async getData() {\n    const url = \'https://stackoverflow.com/\';\n    const response = fetch(url);\n    const data = response.json();\n    this.param2 = data;\n  }\n  loadIframe() {}\n}\n\nexport { SampleClass };\n
Run Code Online (Sandbox Code Playgroud)\n\n

sampleClass.test.js:

\n\n
import { SampleClass } from \'./sampleClass\';\n\ndescribe(\'60146073\', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n  describe(\'#constructor\', () => {\n    it(\'should consturt\', () => {\n      jest.spyOn(SampleClass.prototype, \'constructor\');\n      jest.spyOn(SampleClass.prototype, \'init\').mockReturnValueOnce();\n      const instance = new SampleClass(\'param1\');\n      expect(instance.param1).toBe(\'param1\');\n      expect(instance.init).toBeCalledTimes(1);\n    });\n  });\n  describe(\'#init\', () => {\n    it(\'should init\', async () => {\n      jest.spyOn(SampleClass.prototype, \'getData\').mockResolvedValueOnce();\n      jest.spyOn(SampleClass.prototype, \'loadIframe\').mockReturnValueOnce();\n      jest.spyOn(SampleClass.prototype, \'init\').mockReturnValueOnce();\n      const instance = new SampleClass();\n      await instance.init();\n      expect(instance.getData).toBeCalledTimes(1);\n      expect(instance.loadIframe).toBeCalledTimes(1);\n    });\n  });\n\n  describe(\'#getData\', () => {\n    it(\'should fetch data\', async () => {\n      const mResponse = { json: jest.fn().mockReturnValueOnce({}) };\n      global.fetch = jest.fn().mockResolvedValueOnce(mResponse);\n      jest.spyOn(SampleClass.prototype, \'init\').mockReturnValueOnce();\n      const instance = new SampleClass();\n      await instance.getData();\n      expect(global.fetch).toBeCalledWith(\'https://stackoverflow.com/\');\n      expect(mResponse.json).toBeCalledTimes(1);\n    });\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

100%覆盖率的单元测试结果:

\n\n
 PASS  stackoverflow/60146073/sampleClass.test.js\n  60146073\n    #constructor\n      \xe2\x9c\x93 should consturt (3ms)\n    #init\n      \xe2\x9c\x93 should init (2ms)\n    #getData\n      \xe2\x9c\x93 should fetch data (2ms)\n\n----------------|---------|----------|---------|---------|-------------------\nFile            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s \n----------------|---------|----------|---------|---------|-------------------\nAll files       |     100 |      100 |      80 |     100 |                   \n sampleClass.js |     100 |      100 |      80 |     100 |                   \n----------------|---------|----------|---------|---------|-------------------\nTest Suites: 1 passed, 1 total\nTests:       3 passed, 3 total\nSnapshots:   0 total\nTime:        4.137s, estimated 5s\n
Run Code Online (Sandbox Code Playgroud)\n\n

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60146073

\n