【问题标题】:docker compose jest integration tests cannot make intra-container http requests RequestError: Error: getaddrinfo ENOTFOUNDdocker compose jest 集成测试无法发出容器内 http 请求 RequestError: Error: getaddrinfo ENOTFOUND
【发布时间】:2018-05-12 01:49:03
【问题描述】:

我有一个带有几个容器的 docker compose 堆栈。有问题的两个是一个扩展的python:3-onbuild 容器(参见基本图像here),其中运行着一个 falcon 网络服务器和一个基本的node:8.11-alpine 容器,它试图向 python 网络服务器发出 post 请求。 python 网络服务器正在对postgres:alpine 容器进行数据库调用。这是我的docker-compose.yml 文件的简化版本:

version: '3.6'

services:
  app: # python:3-onbuild
    ports:
      - 5000
    build:
      context: ../../
      dockerfile: infra/docker/app.Dockerfile

  lambda: # node:8.11-alpine
    ports:
      - 10000
    build:
      context: ../../
      dockerfile: infra/docker/lambda.Dockerfile
    depends_on:
      - app

   db: # postgres:alpine
      ports:
        - 5432:5432
      build:
        context: ../../
        dockerfile: infra/docker/db.Dockerfile

我有一套我想要通过的集成测试。当我使用外部世界的端点运行测试时(https python 服务器运行与app 服务相同的代码),所有测试都通过了。当我尝试从我的docker-compose 堆栈内(特别是从lambda 服务到app 服务)对app 服务发出这些请求时,就会出现问题。

我认为这不是时间问题。在我的 jest 套件的 beforeAll 函数中,我轮询 python 服务器 100 秒,每 10 秒一次,如下所示:

在我的玩笑测试中

beforeAll(async () => {
    const endpointUrl = getEndpointUrl();
    const status = await checkStatus(endpointUrl, 10);

    // NOTE: never reaches this line, starts tests before 5-minute timeout
    console.log(`[integration.test]: status = ${status}`);
}, 5 * 60 * 1000); // 5-minute timeout for async function

checkStatus() 的定义位置

/**
 * Checks the status of the backend every 10 seconds, n times
 * @param {string} endpointUrl 
 * @param {number} n 
 */
export function checkStatus(endpointUrl: string, n: number): Promise<string> {
    console.log(`[lib][checkStatus]: before timeout date = ${Date()}`);
    return new Promise<string>((resolve, reject) => {
        checkStatusHelper(endpointUrl, n, resolve, reject);
    });
}

function checkStatusHelper(endpointUrl, n, resolve, reject): void {
    if (n === 0) reject();
    setTimeout(() => {
        console.log(`[lib][checkStatus]: after timeout date ${n} = ${Date()}`);
        rp.get(`${endpointUrl}/status`)
            .then(res => {
                console.log(`[lib][checkStatus]: after request date = ${Date()}`);
                console.log(`[lib][checkStatus]: res = ${res}`);
                resolve('success');
            })
            .catch(err => {
                console.log(`[lib][checkStatus]: err = ${err}`);
                checkStatusHelper(endpointUrl, n - 1, resolve, reject);
            });
    }, 10 * 1000);
}

我得到如下输出(使用request-promise-native):

  console.log src/lib.ts:30
    [lib][checkStatus]: before timeout date = Fri May 11 2018 01:54:10 GMT+0000 (UTC)

  console.log src/lib.ts:39
    [lib][checkStatus]: after timeout date 10 = Fri May 11 2018 01:54:20 GMT+0000 (UTC)

  console.log src/lib.ts:47
    [lib][checkStatus]: err = RequestError: Error: getaddrinfo ENOTFOUND app app:5000

  console.log src/lib.ts:39
    [lib][checkStatus]: after timeout date 9 = Fri May 11 2018 01:54:31 GMT+0000 (UTC)

  console.log src/lib.ts:47
    [lib][checkStatus]: err = RequestError: Error: getaddrinfo ENOTFOUND app app:5000

# etc ...

类似的输出是axios 而不是request-promise-native

  console.log src/lib.ts:30
    [lib][checkStatus]: before timeout date = Fri May 11 2018 01:56:57 GMT+0000 (UTC)

  console.log src/lib.ts:39
    [lib][checkStatus]: after timeout date 10 = Fri May 11 2018 01:57:07 GMT+0000 (UTC)

  console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
    Error: Error: getaddrinfo ENOTFOUND app app:5000
        at Object.dispatchError (/Halloo/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
        at Request.client.on.err (/Halloo/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
        at emitOne (events.js:121:20)
        at Request.emit (events.js:211:7)
        at Request.onRequestError (/Halloo/node_modules/request/request.js:878:8)
        at emitOne (events.js:116:13)
        at ClientRequest.emit (events.js:211:7)
        at Socket.socketErrorListener (_http_client.js:387:9)
        at emitOne (events.js:116:13)
        at Socket.emit (events.js:211:7) undefined

  console.log src/lib.ts:47
    [lib][checkStatus]: err = Error: Network Error

  console.log src/lib.ts:39
    [lib][checkStatus]: after timeout date 9 = Fri May 11 2018 01:57:18 GMT+0000 (UTC)

  console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
    Error: Error: getaddrinfo ENOTFOUND app app:5000
        at Object.dispatchError (/Halloo/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
        at Request.client.on.err (/Halloo/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:676:20)
        at emitOne (events.js:121:20)
        at Request.emit (events.js:211:7)
        at Request.onRequestError (/Halloo/node_modules/request/request.js:878:8)
        at emitOne (events.js:116:13)
        at ClientRequest.emit (events.js:211:7)
        at Socket.socketErrorListener (_http_client.js:387:9)
        at emitOne (events.js:116:13)
        at Socket.emit (events.js:211:7) undefined

  console.log src/lib.ts:47
    [lib][checkStatus]: err = Error: Network Error

# etc ...

我也不认为这不是网络问题。如果我注释掉我的测试步骤并让lambda 服务正常启动,我可以通过 ssh 进入 lambda 容器并使用axiosrequest-promise-native 测试连接。这个/status 端点只返回我数据库中的所有表名,以确保数据库容器也正常运行。这几乎可以立即生效,而且远远早于 100 秒

$ node
> const axios = require('axios')
undefined
> axios.get('http://app:5000/status').then(res => console.log(res.data));
Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }
> [ [ 'table0' ],
    [ 'table1' ],
    [ 'table2' ],
    [ 'table3' ],
    [ 'table4' ],
    [ 'table5' ] ]

我想也许我不能将 jest 用于这些目的,但我觉得我可以,因为当我将 url 更改为在 aws 中运行的生产 https 端点并注释掉我的 jest 中的 beforeAll() 步骤时,一切正常套房。

【问题讨论】:

    标签: http docker docker-compose axios jestjs


    【解决方案1】:

    这最终成为我的笑话配置的问题

    Jest 中的默认环境是通过 jsdom 实现的类似浏览器的环境。如果您正在构建节点服务,则可以使用节点选项来使用类似节点的环境。

    为了解决这个问题,我必须在我的 jest.config.js 文件中添加它:

    {
      // ...
      testEnvironment: 'node'
      // ...
    }
    

    来源:https://github.com/axios/axios/issues/1418

    【讨论】:

      猜你喜欢
      • 2019-01-06
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-02
      • 2021-05-30
      相关资源
      最近更新 更多