簡體   English   中英

如何通過開玩笑和酶測試框架訪問內部的反應組件和模擬api調用?

[英]How to access internal pieces of react component and mock api call with jest & enzyme testing framework?

我正在為一個帶有jest和酶的react-redux組件制作一個javascript單元測試套件; 有問題的組件是一個文件上載表單,其中包含一些字段,這些字段根據用戶輸入和/或服務器響應進行了一些基本樣式更改。 Jest和酶都已設置好並且正常工作,我能夠成功地編寫基本測試。

我想使用jest和酶來模擬用戶與這些UI元素(文件輸入和文本字段)的交互,但我很難這樣做; 我對使用這些測試框架並且對react-redux有一個基本的了解是相當新的,我有點不知所措,以確保正確的部分到位,以便編寫有意義的單元測試。

一般情況下:這個單元測試是在事實之后進行的,幾個月前我加入了這個使用測試驅動開發技術的項目,我之前沒有開發過,所以我將它作為未來開發的示例/模板。

截至目前,單元測試成功地創建了組件(使用酶的mountshallow的mockStore和初始狀態)。 我試過做兩件事:

  1. 根據jest docs創建一個__mocks__ api,用於不同模塊使用的單元測試(一個使用輔助方法進行api調用的redux動作減少器)
  2. 查找/訪問表單字段(文件輸入和文本區域)以模擬用戶交互

我在這兩種情況下都沒有完全成功,並且有單元測試,涵蓋了這些方面,但沒有完全集成的方式。

這是我試圖進行單元測試的組件的render方法:

render() {
    const { dataset } = this.props;

    let serverResp;
    dataset ? serverResp = dataset.fileUploadResp : null;

    let catFeats = this.state.catFeatures;
    let errorMsg = this.state.errorResp;
    let ordFeatureSelection = "";
    let catFeatureSelection = "";
    let dataPrevTable = this.getDataTablePreview();
    // default to hidden until a file is selected, then display input areas
    let formInputClass = "file-upload-form-hide-inputs";

    // server message to display in popup (or other UI element)
    serverResp ? serverResp = ( <p style={{display: 'block'}}> {JSON.stringify(serverResp)} </p> ) :
                 null;
    // check if file with filename has been selected, if so then use css to show form
    this.state.selectedFile && this.state.selectedFile.name ?
      formInputClass = "file-upload-form-show-inputs" : null;

    return (
      <div>
        <Form inverted>
          <Segment className="file-upload-segment">
            <Input
              className="file-upload-form-text-input"
              type="file"
              label="Select new dataset"
              id="upload_dataset_file_browser_button"
              onChange={this.handleSelectedFile}
            />
            <br/>
            <div
              id="file-upload-form-input-area"
              className={formInputClass}
            >
              <Form.Input
                label="Dependent Column"
                placeholder="class"
                value={this.state.dependentCol ? this.state.dependentCol : ""}
                type="text"
                onChange={this.handleDepColField}
              />
              <Form.Input
                label="Ordinal Features"
              >
                <textarea
                  label="Ordinal Features"
                  placeholder={"{\"ord_feat_1\": [\"MALE\", \"FEMALE\"], \"ord_feat_2\": [\"FIRST\", \"SECOND\", \"THIRD\"]}"}
                  onChange={this.handleOrdinalFeatures}
                />
              </Form.Input>
              <Form.Input
                label="Categorical Features"
              >
                <textarea
                  label="Categorical Features"
                  placeholder={"cat_feat_1, cat_feat_2"}
                  onChange={this.handleCatFeatures}
                />
              </Form.Input>
              <Popup
                header="Error Submitting Dataset"
                content={serverResp}
                open={errorMsg ? true : false}
                trigger={
                  <Button
                    inverted
                    color="blue"
                    compact
                    size="small"
                    icon="upload"
                    content="Upload dataset"
                    onClick={this.handleUpload}
                  />
                }
              />
            </div>
          </Segment>
        </Form>
        {dataPrevTable}
      </div>
    );
  }

它是一個相當基本的反應組件,連接到app redux商店,帶有一些語義ui的東西,可以很好地造型。 有一個帶有文件輸入,文本區域輸入和按鈕/彈出窗口的表單; 如果未選擇任何文件,則僅顯示文件輸入,如果提交文件的嘗試不成功,則彈出窗口中將顯示錯誤消息。

對於第1點 - 我試圖遵循jest中的指南/ docs並創建組件使用的模擬api片段並使用jest.mock()

jest.mock('../../utils/apiHelper');
import uploadDataset from '../../data/datasets/dataset/api';

但是當我嘗試時,在單元測試中

  it('testing promise for successfully case, proper dependent_col', () => {
    expect.assertions(1);
    return uploadDataset(fakeDataset).then(data => expect(data.name).toEqual('iris.csv'));
  })

測試因TypeError: (0 , _api2.default) is not a function失敗TypeError: (0 , _api2.default) is not a function我直接導入mock api並直接調用它TypeError: (0 , _api2.default) is not a function ,它工作正常但無法測試應該進行api調用的模塊; 我覺得以這種方式測試這個功能幾乎是一個沒有實際意義,並且更願意以正確模擬它實際工作方式的方式測試組件,即觸發導致api調用的事件而不是直接調用api 。 應該如何使用jest.mock() 我不正確地使用它?

對於第2點 - 我正在直接操作組件反應狀態並檢查UI更新,而不是通過表單字段模擬用戶輸入。 我嘗試使用酶的find來訪問文件輸入字段

let testFileUpload;

beforeEach(() => {
  testFileUpload = mount(<FileUpload store={store} testProp="hello" />);
})

... other tests ...

it('click file upload button', () => {
 testFileUpload.find('#upload_dataset_file_browser_button').simulate("change", 
 {
       target: {
         files: [ 'iris.csv' ]
       }
     });
 })
}

並且測試失敗並出現錯誤Method “simulate” is meant to be run on 1 node. 2 found instead. Method “simulate” is meant to be run on 1 node. 2 found instead. 我應該如何通過ID訪問文件輸入/ html元素和/或酶對模擬的期望是什么? 我花了最近幾天查看jest / enzyme文檔和示例,需要一些幫助。 當只有一個具有該id的元素時,為什么find方法返回2個節點? 我應該如何在所述節點上模擬文件選擇的更改事件? 與上面提到的解決方法類似,我正在直接更改組件的狀態並從該點檢查事物,但我更願意盡可能地模擬實際用例。

任何幫助是極大的贊賞。

盡管如此,是否可以繞過單元測試中的某些事情來基本上完成相同的結果? 有了我的問題,我在模擬輸入到表單字段時遇到了一些麻煩,該表單字段應該在用戶輸入/更改時使用react setState,所以我只是直接更改狀態而不是通過UI元素獲取輸入。 熟悉單元測試的人認為,這種單元測試方式是否足夠或者這是非常不正確的? 現在我幾乎是唯一一個為這個項目的前端UI組件進行單元測試的人,我不太確定如何正確測試這些部分。

不確定為什么帶有#id的元素被掛載兩次。 但你可以使用索引:

testFileUpload.find('#upload_dataset_file_browser_button').at(0).simulate("change")

我曾經認為酶的工作原理與jquery與css選擇器相同。 但似乎不是。 即使是庫的創建者也不建議使用帶模擬操作的mount。 但我仍然使用,因為這是我在測試中獲得良好報道的最佳方式。 使用酶我主要使用元素選擇器而不是css選擇器。

我使用prop來模擬動作,因為模擬不能真正“模擬”自定義動作。 嘗試這個:

testFileUpload.find(Input).prop('onChange')('paramatertosendtofunction')

編輯:您可以使用輔助函數

function flushPromises() {
  return new Promise(resolve => setImmediate(resolve));
}


test('', () => {
  testFileUpload.find(Input).prop('onChange')('paramatertosendtofunction')
  testFileUpload.update()
  return flushPromises().then(() => {
    expect(textFileUpload.state.foo).toBe('bar')
  });
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM