【问题标题】:Express/Mongoose/Jest error: ECONNABORTEDExpress/Mongoose/Jest 错误:ECONNABORTED
【发布时间】:2019-07-22 23:42:31
【问题描述】:

我有一个内置在 Express 中的 API,我正在使用 Jest 对其进行测试。当我使用 Postman 进行测试时,API 工作得很好,但是当我运行我的测试套件时,我通常在使用 .attach() 上传文件时收到 ECONNABORTED 错误。 (有时,它工作得很好。)我正在使用一套中间件来下载一组由 URL 引用的图像,然后是通过表单上传传递给端点的任何图像。保存图像后,我使用第三个中间件来调整图像大小并将它们保存在子目录中。由于错误仅发生在 Jest 中,因此错误似乎就在于此,但我也不肯定我正在正确处理 Multer 的错误。

// endpoint.js

const storage = multer.diskStorage({
  destination: async (req, file, cb) => {
    // Check for product's existence
    if (product) {
      // Make the directory if necessary
      cb(null, /* location */)
    } else {
      cb(404, null)
    }
  },
  filename: async (req, file, cb) => {
    cb(
      null, /* location */}`
    )
  }
})

const upload = multer({ storage }).array("files")

router.post(
  "/:id",
  async (req, res, next) => {
    // Download images from URLs if provided
    next()
  },
  (req, res, next) => {
    upload(req, res, err => {
      // Handle errors (e.g. return res.status(404).json({ message: "Product not found" })
    })
    next()
  },
  async (req, res) => {
    // resize and save to subdirectory
  }
)
// endpoint.test.js

describe("/endpoint", () => {
  describe("POST", () => {
    it("saves uploaded images to the server", async () => {
      const response = await request(app)
        .post(`/endpoint/${id}`)
        .attach("files", "assets/img-test-1.jpg")
        .attach("files", "assets/img-test-2.jpg")
        .set("Content-Type", "multipart/form-data")

      expect(response.status).toEqual(201)
    }, 30000)

  ...

})

编辑:通过将 next() 调用移动到 Multer 处理程序中修复了原始错误。但是,现在发生了相同的错误,只是在不同的测试中。同样,该错误仅在由测试脚本运行时发生;通过 Postman 拨打相同的电话时,我没有遇到任何问题。

// endpoint.js

let errors
router.post(
  "/:id",
  async (req, res, next) => {
    errors = []

    ...

    // This is the problematic call. If I explicitly set
    // product = null, the test runs normally
    const product = await Product.findById(req.params.id)
    if (!product) {
      errors.push({ status: 404, message: "Product not found" })
      return next()
    }

    ...

    return next()
  },
  // Several more middleware functions
})
// endpoint.test.js

...

beforeAll(done => {
  app.on("ready", async () => {
    const newProduct = await Product.create(product)
    id = newProduct._id
    done()
  })
})

...
describe("/api/bam/images", () => {
  describe("POST", () => {
    ...
    it("returns a 404 error if the associated product is not found", async () => {
      const response = await request(app)
        .post("/api/bam/images/000000000000000000000000")
        .attach("files", "assets/img-test-1.jpg")
        .attach("files", "assets/img-test-2.jpg")

      expect(response.status).toEqual(404)
    })
  })
})

【问题讨论】:

    标签: node.js express mongoose jestjs multer


    【解决方案1】:

    我认为问题可能与在 multer 完成上传之前调用 next() 有关 - 尝试在上传回调中移动下一步:

    (req, res, next) => {
        upload(req, res, err => {
          // Handle errors (e.g. return res.status(404).json({ message: "Product not found" 
          next()
          })
        })
    
      },
    

    PT2:与编辑相关,如果问题似乎与 await 调用有关,则可能会抛出错误但未捕获 - 当您等待被拒绝的承诺时,它的行为就像正常抛出一样。扔在这里意味着next永远不会被调用:

        // This is the problematic call. If I explicitly set
        // product = null, the test runs normally
        try {
          const product = await Product.findById(req.params.id)
          if (!product) {
            errors.push({ status: 404, message: "Product not found" })
            return next()
          }
        } catch (err) {
          return next(err)
        }
    
    

    【讨论】:

    • 这在我运行测试的前两次有效,但现在又失败了。我还尝试将 next() 包装在 else 块中,但也没有运气。
    • 更正:这确实修复了之前发生的错误,但现在它已移至新位置。经过进一步调查,似乎与Mongoose有关,但我无法确定问题所在。查看对原始帖子的修改。
    • @EricToler 更新了答案以尝试帮助下一部分
    • 终于回到了这个项目,这个解决方案似乎已经解决了这个问题。我仍然偶尔会失败,但再次运行测试会导致通过。我觉得偶然的失败只是文件上传测试的副作用,而且由于问题似乎在生产中不存在,我可以忍受偶尔需要运行两次测试。谢谢!
    猜你喜欢
    • 2020-10-17
    • 1970-01-01
    • 2021-03-17
    • 2021-08-05
    • 2019-04-26
    • 2021-12-20
    • 2020-07-30
    • 2021-05-25
    • 2020-04-17
    相关资源
    最近更新 更多