【问题标题】:Async setup of environment with Jest使用 Jest 异步设置环境
【发布时间】:2018-07-08 14:18:48
【问题描述】:

Jest 中运行 e2e 测试之前,我需要从服务器获取身份验证令牌。

是否可以全局执行此操作并以某种方式将其设置为每个测试的全局环境/上下文?

我用globalSetup 配置选项试了一下:

const auth = require('./src/auth')
const ctx = require('./src/context')

module.exports = () => {
    return new Promise(res => {
        auth.getToken()
            .then(token => {
                ctx.init({token})
                global.token = token
                res()
            })

    })
}

context.js

let _token

const init = ({token}) => {
    _token = token
}

const getToken = () => {
    return _token
}

module.exports = {
    init,
    getToken

}

但是global.tokenctx.getToken() 都返回未定义。

我需要使用帮助脚本并将令牌作为 env var 传递,然后将其设置为 global

  "scripts": {
    "test": "TOKEN=$(node src/get-token.js) jest"
  },

有没有更好的方法(不涉及shell)?

【问题讨论】:

    标签: javascript jestjs e2e-testing


    【解决方案1】:

    在我的情况下,我必须获得一次当前会话的令牌。在这里,我在 jest 配置中使用了 globalSetup 属性。参考:https://jestjs.io/docs/en/configuration#globalsetup-string

    我的 jest.config:

    module.exports = {
      globalSetup: "./tests/global-setup.js",
      // ..other config... 
      globals: {
          TEST_EMAIL: 'test@test.com',
          TEST_PASSWORD: 'some_password',
      }
    }
    

    global-setup.js:

     module.exports = async function() {
      const getSessionToken = () => {
        // api call to get SessionToken
        /* return fetch() */
      }
    
      sessionToken = await getSessionToken();
      process.env.SESSION_TOKEN = sessionToken;
     }
    
    

    【讨论】:

      【解决方案2】:

      我无法根据异步条件的结果跳过测试 (test.skip)。测试确定它们是否要在我的全局异步条件解决之前运行。我什至尝试使用beforeAll 并等待我的承诺得到解决,但是在测试中我的条件已经解决,当测试确定它们是否要运行时,承诺未解决,我的 var 未定义。

      我最终在scripts/isLocalCmsRunningOn3030.sh 中使用 bash 完成此操作:

      #!/bin/bash
      
      if [[ $(lsof -i :3030 | grep 'node' | grep 'LISTEN') ]]; then
        echo TRUE
      else
        echo FALSE
      fi
      

      package.json:

      IS_CMS_RUNNING=$(scripts/isLocalCmsRunningOn3030.sh) jest
      

      在我的setupFile.js

      global.testIf = (condition) => (condition ? test : test.skip);
      

      在我的测试文件中

        testIf(process.env.IS_CMS_RUNNING === 'TRUE')('testname', () => {
        });
      

      【讨论】:

        【解决方案3】:

        有一个名为:setupFiles 的 CLI/config 选项,它在执行测试代码之前立即运行。

        "jest": {
          "globals": {
            "__DEV__": true,
            ...
          },
          "setupFiles": [
            "./setup.js"
          ]
        }
        

        setup.js 可能类似于:

        (async function() {
            // const { authToken } = await fetchAuthTokens()
            global.authToken = '123'
        })()
        

        然后您可以直接在每个测试套件(文件)中访问authToken,例如beforeAll(_ => console.log(authToken)) // 123


        但是,如果您想要一个全局设置运行每个工作程序(cpu 核心)而不是每个测试文件(默认情况下推荐,因为测试套件是沙盒的)。根据当前的 jest API 限制,您可以选择通过 testEnvironment 选项自定义测试的运行时环境。然后你需要实现一个自定义类,扩展jsdom/node 环境暴露setup/runScript/teardown api。

        例子:

        customEnvironment.js

        // my-custom-environment
        const NodeEnvironment = require('jest-environment-node');
        
        class CustomEnvironment extends NodeEnvironment {
          constructor(config) {
            super(config);
          }
        
          async setup() {
            await super.setup();
            const token = await someSetupTasks();
            this.global.authToken = token;
          }
        
          async teardown() {
            await super.teardown();
            await someTeardownTasks();
          }
        
          runScript(script) {
            return super.runScript(script);
          }
        }
        

        我的测试.js

        let authToken;
        
        beforeAll(() => {
          authToken = global.authToken;
        });
        

        【讨论】:

        • 是的,但是 globalSetup/globalTeardown API用于根据需要注入上下文,它主要用于繁重的实例化任务,例如启动和关闭浏览器实例。跨度>
        • 我们可以将它与 create-react-app 一起使用吗?如果可以,能否给个链接?
        • 这只能使用硬编码的值。当涉及到异步函数时,token 总是未定义的。
        • if you want a global setup that runs per worker(cpu core) instead of per test file:文档说TestEnvironment is sandboxed. Each test suite will trigger setup/teardown in their own TestEnvironmenthttps://jestjs.io/docs/en/configuration.html#testenvironment-string
        • TestEnvironment 与测试中的 JS 上下文也不同。如果您导入并比较 TestEnvironment 和测试之间的导入实例,您会发现类没有等效解析(即 instanceof 在应该返回 true 时没有返回)。对于提交的问题,TestEnvironment 应该足够了
        猜你喜欢
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        • 2021-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-05
        • 1970-01-01
        相关资源
        最近更新 更多