首页 > 解决方案 > Jest 集成测试 Express REST API 与 Mongoose

问题描述

大家。我是单元/集成测试的新手,在测试我的一个 API 路由时遇到了问题,其中涉及文件系统操作和 Mongoose 模型方法调用。我需要能够模拟猫鼬模型方法以及路由器的 post 方法。分享一下我路由器的post方法。

文档.js

const { User } = require('../models/user');
const { Document } = require('../models/document');
const isValidObjectId = require('./../helpers/isValidObjectId');
const createError = require('./../helpers/createError');
const path = require('path');
const fs = require('fs');
const auth = require('./../middlewares/auth');
const uploadFile = require('./../middlewares/uploadFile');
const express = require('express');
const router = express.Router();

.
.
.
router.post('/mine', [auth, uploadFile], async (req, res) => {
    const user = await User.findById(req.user._id);

    user.leftDiskSpace(function(err, leftSpace) {
        if(err) {
            return res.status(400).send(createError(err.message, 400));
        } else {
            if(leftSpace < 0) {
                fs.access(req.file.path, (err) => {
                    if(err) {
                        res.status(403).send(createError('Your plan\'s disk space is exceeded.', 403));
                    } else {
                        fs.unlink(req.file.path, (err) => {
                            if(err) res.status(500).send('Silinmek istenen doküman diskten silinemedi.');
                            else res.status(403).send(createError('Your plan\'s disk space is exceeded.', 403));
                        });
                    }
                });
            } else {
                let document = new Document({
                    filename: req.file.filename,
                    path: `/uploads/${req.user.username}/${req.file.filename}`,
                    size: req.file.size
                });
        
                document.save()
                    .then((savedDocument) => {
                        user.documents.push(savedDocument._id);
                        user.save()
                            .then(() => res.send(savedDocument));
                    });
            }
        }
    });
});
.
.
.

module.exports = router;

文档.test.js

const request = require('supertest');
const { Document } = require('../../../models/document');
const { User } = require('../../../models/user');
const mongoose = require('mongoose');
const fs = require('fs');
const path = require('path');
const config = require('config');

let server;

describe('/api/documents', () => {
    beforeEach(() => { server = require('../../../bin/www'); });
    afterEach(async () => {
        let pathToTestFolder = path.join(process.cwd(), config.get('diskStorage.destination'), 'user');
        
        await fs.promises.access(pathToTestFolder)
            .then(() => fs.promises.rm(pathToTestFolder, { recursive: true }))
            .catch((err) => { return; });

        await User.deleteMany({});
        await Document.deleteMany({});

        server.close();
    });

    .
    .
    .

    describe('POST /mine', () => {
        let user;
        let token;
        let file;

        const exec = async () => {
            return await request(server)
                .post('/api/documents/mine')
                .set('x-auth-token', token)
                .attach('document', file);
        }

        beforeEach(async () => {
            user = new User({
                username: 'user',
                password: '1234'
            });
            user = await user.save();

            user.leftDiskSpace(function(err, size) { console.log(size); });

            token = user.generateAuthToken();

            file = path.join(process.cwd(), 'tests', 'integration', 'files', 'test.json');
        });

        .
        .
        .

        it('should return 400 if an error occurs during calculation of authorized user\'s left disk space', async () => {
            jest.mock('../../../routes/documents');
            let documentsRouter = require('../../../routes/documents');
            
            let mockReq = {};
            let mockRes = {}

            let mockPostRouter = jest.fn();
            mockPostRouter.mockImplementation((path, callback) => {
                if('path' === '/mine') callback(mockReq, mockRes);
            });

            documentsRouter.post = mockPostRouter;
            
            let error = new Error('Something went wrong...');

            const res = await exec();

            console.log(res.body);

            expect(res.status).toBe(400);
            expect(res.body.error).toHaveProperty('message', 'Something went wrong...');
        });
        .
        .
        .
    });
});

我想要做的是,我需要能够在路由处理程序中调用模拟user.leftDiskSpace(function(err, leftSpace))用户模型方法。router.post('/mine', ...)我需要能够通过回调函数进入 if 和 else 分支user.leftDiskSpace()。我怎样才能做到这一点?

提前致谢。

标签: expresstestingmongoosejestjssupertest

解决方案


推荐阅读