Jest Memory Leak测试Express中间件

时间:2019-05-07 16:49:59

标签: node.js unit-testing express jestjs supertest

我正在尝试对Express的身份验证中间件进行单元测试。中间件非常简单,可以在下面完整查看:

const admin = require('./../config/firebase/firebase');

// Models - User
const User = require('./../models/user');

const auth = async (req, res, next) => {
    try {
        // The Authorization Bearer Token sent in the header of the request needs to be decoded.
        const token = req.header('Authorization').replace('Bearer ', '');
        const decoded = await admin.auth().verifyIdToken(token);

        // Finding that user in the database by their Firebase UID.
        const user = await User.findOne({ _id: decoded.uid });

        // If that user does not exist, we'll throw an error.
        if (!user) {
            throw new Error();
        }

        // Making the user accessible to the endpoint.
        req.user = user;

        // Proceed
        next();
    } catch (e) {
        // HTTP 404 Unauthorized Response Status
        res.status(401).send({ error: 'Please authenticate.' });
    }
}

module.exports = auth;

由于Firebase Admin SDK返回一个包含用户UID作为属性的对象,出于测试目的,我创建了一个“伪令牌”,它只是一个具有UID属性的对象。然后,我对Admin SDK进行了模拟,以便它返回传入的内容,如下所示:

module.exports = {
    auth() {
        return this;
    },
    verifyIdToken(token) {
        return JSON.parse(token);
    },
    initializeApp(app) {
    },
    credential: {
        cert() {

        }
    }
}

由于auth中间件希望在测试数据库中找到用户,因此我必须在beforeAll钩子中将其配置为Jest Setup:

const userOneToken = JSON.stringify({ uid: 'example UID' });
const userOne = {
    _id: 'example UID',
    // ...
};

beforeAll(async () => {
    await User.deleteMany();
    await User.save(userOne);
    app.use(auth).get('/', (req, res) => res.send());
});

这意味着中间件将始终能够获得UID作为回报,该UID可用于在测试数据库中查找测试用户。

导入我的Express Application之后,测试套件本身非常简单,只需进行三个测试:

const auth = require('./../../src/middleware/auth');

describe('Express Auth Middleware', () => {
    test('Should return 401 with an invalid token', async () => {        
        await request(app)
            .get('/')
            .set('Authorization', 'Bearer 123')
            .send()
            .expect(401);   
    });

    test('Should return 401 without an Authorization Header', async () => {        
        await request(app)
            .get('/')
            .send()
            .expect(401);   
    });

    test('Should return 200 with a valid token', async () => {        
        await request(app)
            .get('/')
            .set('Authorization', `Bearer ${userOneToken}`)
            .send()
            .expect(200);   
    });
});

但是,似乎测试正在泄漏内存(显然是通过使用--detectLeaks标志进行调用)。此外,看来Jest还在寻找上次测试遗留下来的打开手柄。使用--detectOpenHandles标志运行套件会在上次测试的TCPSERVERWRAP请求中返回get错误。

提出了可能的解决方案in this GitHub issue,但没有一个对我有用。

任何帮助解决此问题的方法将不胜感激,因为我的所有测试套件都依赖于Supertest来泄漏内存。谢谢。

0 个答案:

没有答案