web-dev-qa-db-ja.com

JestでのXHRテスト

AJAXメソッド(Vanilla XHR)をテストしたいのですが、Jestフレームワークでそれを行う方法が見つかりません。Jasmineのmock-ajax.jsを見つけました、問題は私がそれをインストールする方法を見つけることができないということです。

JestでAjax関数を単体テストするより良い方法はありますか?

16
Tomasz Kasperek

Jest apiが少し変更されました。これが私が使っているものです。それは何もしませんが、私のコンポーネントをレンダリングするのに十分です。

const xhrMockClass = () => ({
  open            : jest.fn(),
  send            : jest.fn(),
  setRequestHeader: jest.fn()
})

window.XMLHttpRequest = jest.fn().mockImplementation(xhrMockClass)

およびテストファイル内:

import '../../__mock__/xhr-mock.js'

20
ThaJay

追加のパッケージなしでJestでXHRをテストできます。これは、XMLHttpRequestのモックオブジェクトを作成するヘルパー関数です。

let open, send, onload, onerror;

function createXHRmock() {
    open = jest.genMockFn();

    // be aware we use *function* because we need to get *this* 
    // from *new XmlHttpRequest()* call
    send = jest.genMockFn().mockImpl(function(){   
        onload = this.onload.bind(this);
        onerror = this.onerror.bind(this);
    });

    const xhrMockClass = function () {
        return {
            open,
            send
        };
    };

    window.XMLHttpRequest = jest.genMockFn().mockImpl(xhrMockClass);
}

そして、次のようにテストで使用できます。

it('XHR success', () => {
    createXHRmock();

    // here you should call GET request

    expect(open).toBeCalledWith('GET', 'http://example.com', true);
    expect(send).toBeCalled();

    // call onload or onerror
    onload();

    // here you can make your assertions after onload
});
15

前述のように、追加のライブラリは必要ありません。

 // mocks.js is file where you could put your mocks (example below)
 const mocks = require('./mocks.js')

 test('XHR test', () => {
   let xhrMock = {
      open: jest.fn(),
      setRequestHeader: jest.fn(),
      onreadystatechange: jest.fn(),
      send: jest.fn(),
      readyState: 4,
      responseText: JSON.stringify(mocks),
      status: 200
    }

   window.XMLHttpRequest = jest.fn(() => xhrMock)
   xhrMock.onreadystatechange()

   sendData().then((response) => {
      // You could do you checks here. Some examples:
      expect(xhrMock.setRequestHeader).toBeCalledWith('Cache-Control', 'no-cache')
      expect(xhrMock.open).toBeCalledWith('POST', 'you_api_url.com/end_point/')
      expect(xhrMock.withCredentials).toBe(false)

      let formData = new FormData()
      formData.append('firstParam', 'firstParamValue')  

      expect(yoloRequestMock.send).toBeCalledWith(formData)
      expect(JSON.stringify(response)).toBe(JSON.stringify(mocks))
   })

    // the following function is the one which sends the request (to be tested)
    function sendData() {
       return new Promise(function(resolve, reject) {
         let formData = new FormData()
         formData.append('firstParam', 'firstParamValue')
         let xhr = new XMLHttpRequest()
         xhr.withCredentials = false
         xhr.onreadystatechange = function () {
           if (this.readyState === 4) {
             if(xhr.status === 200) {
               resolve(JSON.parse(xhr.responseText))
             } else {
               reject(xhr.responseText)
             }
           }
         }
         xhr.open('POST', T2S_VISUAL_SEARCH_PARAMS.t2sVisualSeacchApiUrl)
         xhr.setRequestHeader("Cache-Control", "no-cache");
         xhr.send(formData)
       })
    }
  }

ファイル mocks.jsモックが含まれています:

module.exports =
  {
    response: {
      body: { ... }
    }
  }
1
M3HD1