在我的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
会抱怨该行9
是Uncovered Line
(在我的示例中,它是next(err)
函数),我如何在我的例子中模拟错误?
答案 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);