【问题标题】:React (Native) setup Jest to test Context componentReact (Native) 设置 Jest 来测试 Context 组件
【发布时间】:2019-05-03 09:12:35
【问题描述】:

React Context API 允许我将应用程序状态的逻辑放在一个地方(并避免使用 redux)。现在看起来是这样的

// Using the Context API used in react 16.3 - https://www.youtube.com/watch?v=XLJN4JfniH4
const { Provider, Consumer: ContextConsumer } = React.createContext()

class ContextProvider extends Component {

  ...// lot of functions ...

  render() {
    return (
      <Provider
        value={{
          ...this.state,
          getDose: this.getDose,
          getDoseRange: this.getDoseRange,
          setDose: this.setDose,
          checkIN: this.checkIN,
          checkOUT: this.checkOUT,
          getFalsifiedDrug: this.getDefaultproductData,
          updatePrescriptionDose: this.updatePrescriptionDose,
        }}
      >
        {this.props.children}
      </Provider>
    )
  }
}

module.exports = { ContextConsumer, ContextProvider }

完整的代码可以在here找到。

构建 jest 测试的最佳实践是什么,让我可以测试功能并且不会弄乱状态?

(希望避免使用 Enzyme(由 AirBnB 开发)-因为AirBnB officially gave up using React Native

示例

如何进行测试以确认当我调用 setDose(2)productData.dose 已从 "5 mg" 更改为现在等于 "2 mg。但随后将状态设置回"5 mg" 以进行其他测试。

奖励信息

我无法让 jest 与我合作(因此我可以尝试建议的解决方案)

package.json

{
  "main": "node_modules/expo/AppEntry.js",
  "private": true,
  "scripts": {
    "test": "jest --watchAll"
  },
  "dependencies": {
    "@expo/samples": "2.1.1",
    "crypto-js": "^3.1.9-1",
    "date-fns": "^1.29.0",
    "expo": "^28.0.0",
    "invert-color": "^1.2.3",
    "lodash": "^4.17.10",
    "react": "16.3.1",
    "react-native": "https://github.com/expo/react-native/archive/sdk-28.0.0.tar.gz",
    "react-native-qrcode": "^0.2.6",
    "react-native-slider": "^0.11.0",
    "react-native-switch": "^1.5.0",
    "react-navigation": "2.3.1",
    "whatwg-fetch": "^2.0.4"
  },
  "devDependencies": {
    "babel-eslint": "^10.0.1",
    "babel-preset-expo": "^5.0.0",
    "eslint": "^5.16.0",
    "eslint-config-codingitwrong": "^0.1.4",
    "eslint-plugin-import": "^2.17.2",
    "eslint-plugin-jest": "^22.5.1",
    "eslint-plugin-jsx-a11y": "^6.2.1",
    "eslint-plugin-react": "^7.13.0",
    "jest-expo": "^32.0.0",
    "react-native-testing-library": "^1.7.0",
    "react-test-renderer": "^16.8.6"
  },
  "jest": {
    "preset": "jest-expo"
  }
}

它只是把这个扔给我

> @ test /Users/norfeldt/Desktop/React-Native/MedBlockChain
> jest --watchAll

● Validation Error:

  Module react-native/jest/hasteImpl.js in the haste.hasteImplModulePath option was not found.
         <rootDir> is: /Users/norfeldt/Desktop/React-Native/MedBlockChain

  Configuration Documentation:
  https://jestjs.io/docs/configuration.html

npm ERR! Test failed.  See above for more details.

我尝试过类似

rm -rf node_modules/ yarn.lock package-lock.json && npm install

【问题讨论】:

  • 我想你可以使用:github.com/airbnb/enzyme,这个库提供了一个很好的API来测试状态等等。
  • 谢谢,但 AirBnB 已经停止使用 React Native,所以我希望避免使用它,因为我希望它只针对 React (web)。

标签: javascript reactjs react-native jestjs


【解决方案1】:

您可以使用您已经在项目规范中使用的react-test-renderer
你需要调用testRenderer.getInstance() => 检查当前state => 调用一些你需要测试的方法 => 检查更新的state

import React from "react";
import { create } from "react-test-renderer";
import { ContextProvider } from "../Context";

describe("ContextProvider", () => {
  test("it updates dose correctly", () => {
    const component = create(<ContextProvider />);
    const instance = component.getInstance();

    expect(instance.getDose()).toBe(5);
    expect(instance.state.productData.dose).toBe("5 mg");

    instance.setDose(2);

    expect(instance.getDose()).toBe(2);
    expect(instance.state.productData.dose).toBe("2 mg");
  });

  test("it updates something else correctly", () => {
    // ...
  });
});

其他测试的状态不会受到影响。

here 所述,我唯一需要使用您的存储库进行这项工作的就是npm install whatwg-fetch@2.0.4 --save。希望这会有所帮助。

更新

尽管这应该是另一个问题并且显而易见的解决方案是创建一个新的 rn 项目并在其中复制代码,但这是我为修复代码中的 jest 错误所做的工作:

1) 使版本匹配(如 cmets 中所述...):

"expo": "^32.0.0",
"jest-expo": "^32.0.0",
// and maybe even
"react-native": "https://github.com/expo/react-native/archive/sdk-32.0.0.tar.gz",

2) 修复错误

api.caller 不是函数

按照here 的描述使用babel.config.js

module.exports = function(api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    env: {
      development: {
        plugins: ["transform-react-jsx-source"]
      }
    }
  };
};

3)由于this而使用yarn

【讨论】:

  • 您的回答对我来说很有意义。我只是无法让jest 与我合作,所以我可以尝试一下。它不断抛出Validation ErrorModule react-native/jest/hasteImpl.js in the haste.hasteImplModulePath option was not found.
  • 我尝试过类似m -rf node_modules/ yarn.lock package-lock.json &amp;&amp; npm install
  • 这很奇怪。没遇到过这个问题。首先想到的是make expo and jest-expo versions match。也不要混合使用 npm 和 yarn。坚持一件事,因为它可能会导致一些问题。这是another suggestion to try
  • 我实际上已经浏览了你之前建议的所有网站,但我无法让它工作。
【解决方案2】:

如果您正在寻找 Enzyme 的替代品,我认为您应该看这里:https://callstack.github.io/react-native-testing-library/

该库将允许您使用提供的update 函数来更改您正在测试的值,然后将它们更改回来。

React Native 的优秀库 - the getting started page says it all。如果您对一些帮助您入门的代码感兴趣,我也可以做一些事情。

【讨论】:

    【解决方案3】:

    我建议您只对您的逻辑进行单元测试,并考虑在这种情况下完全避免组件测试。

    您可以将您的方法提取到“Presenter”中以处理您的数据并仅测试此逻辑。使用这种方法很容易测试具有纯输入/输出逻辑的演示者。

    例如,演示者可能如下所示:

    // DosePresenter.js
    
    const processDose = (value, productData) => {
      productData.dose = value.toFixed(0) + productData.dose.replace(/[\d\.]*/g, '')
      productData.productionTime = Conventions.datetimeStr();
      productData.hashSalt = this.makeHashSalt();
      return {productData, productDataHash: getHashOfproductData(productData)};
    };
    
    module.exports = {
      processDose
    };
    

    用法:

    // Context.js
    
    import * as DosePresenter from './DosePresenter';
    
    const setDose = (value) => this.setState(DosePresenter.processDose(value, {...this.state}));
    

    现在应该更容易测试逻辑了:

    // DosePresenter.test.js
    
    describe('DosePresenter tests', () => {
      let uut;
    
      beforeEach(() => {
        uut = require('./DosePresenter');
      });
    
      it('should process a dose', () => {
        const value = 10;
        const productData = {};
        expect(uut.processDose(value, productData)).toEqual(...);
      });
    };
    

    【讨论】:

      猜你喜欢
      • 2019-10-30
      • 1970-01-01
      • 2021-08-08
      • 2016-07-22
      • 1970-01-01
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      • 2018-01-29
      相关资源
      最近更新 更多