使用异步函数模拟请求错误

时间:2017-09-10 05:37:05

标签: node.js async-await mocha istanbul supertest

在我的express应用中,我声明了这样的请求处理程序(在此简化):

export const CreateProduct = async (req, res, next) => {
  try {
    // ProductModel is a sequelize defined model
    const product = await ProductModel.create(req.body)
    res.send(product)
  } catch (err) {
    // I have raygun setup as the error handler for express
    // in this example, it will finally return 500
    next(err)
  }
}

然后像这样使用它:

import { CreateProduct } from './create_product'

export const ProductRouter = express.Router()
ProductRouter.post('/', CreateProduct)

但是,在运行我的测试时,nyc / istanbul会抱怨该行9Uncovered Line(在我的示例中,它是next(err)函数),我如何在我的例子中模拟错误?

2 个答案:

答案 0 :(得分:2)

更容易实现为ProductModel创建验证机制,当您使用无效数据创建产品时会产生一些验证错误。

在您的摩卡咖啡中,您将发送无效的产品正文,它会抓住您的next

答案 1 :(得分:2)

最简单的两种方法如下:

1)承认控制器不能进行单元测试,并且因为它们不能进行单元测试,它们将成为集成测试的一部分,因为这是真的,你将移出尽可能多的单元可测试代码它们在物理上是可能的,并且限制它们只是编写能够被测试的代码片段。这没关系;从单个请求的角度来看,Express控制器有点像main方法,只要main方法就可以将硬概念混合在一起来决定构建的内容是否合适。 1}}并不是在进行繁重的工作,而是实例化和运行正在进行的工作。

2)编写你的功能,使他们都能获得所需的所有道具,完成他们的工作,而且他们几乎总是从其他文件(不是他们定义的文件)中接收它们,除非赋值只是一个默认值。

对于控制器,如果您希望控制器是可单元测试的,您可以预先配置它以接受ProductModel使用(或使用的功能),而不是假设您要拉在真实模型中。

export const CreateProduct = (ProductModel) => async (req, res, next) => {
  const productData = req.body
  try {
    const product = await ProductModel.create(productData)
    res.send(product)
  } catch (err) {
    next(err)
  }
}



import { CreateProduct } from './create_product'
import { ConfigureProductModel } from './somewhere_else'

export const ProductRouter = express.Router()
ProductRouter.post('/', CreateProduct(ConfigureProductModel(database)))

现在要对此进行测试,您可以轻松创建CreateProduct,传递假ProductModel。如果您使用ConfigureProductModel作为工厂的示例,则可以通过向其传递假数据库实例来测试 it (如果您这样做,确实具有该级别的控制权)。 / p>

就个人而言,就像我说的那样,作为一个控制器,我希望尽可能多地删除控件,所以我可能会把大部分命令性代码带走。

const CreateProduct = ProductModel => (req, res, next) =>
  ProductModel.create(req.body)
    .then(product => res.send(product))
    .catch(next);