使用Jest异步设置环境

时间:2018-01-29 19:44:11

标签: javascript jest e2e-testing

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)?

3 个答案:

答案 0 :(得分:8)

有一个名为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);
  }
}

MY-test.js

let authToken;

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

答案 1 :(得分:0)

基于异步条件的结果,我找不到跳过测试(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', () => {
  });

答案 2 :(得分:0)

我的情况是,我必须为当前会话获取一次令牌。在这里,我在玩笑配置中使用了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;
 }

相关问题