如何测试快速会话

问题描述

我正在测试创建项目 API。现在,为了创建一个项目,中间件将令牌检查到 cookie 中,以及数据库中是否存在会话。问题是,即使从第一次调用登录 API 开始创建会话(我可以在数据库中看到它),创建项 API 也无法“读取”会话。是不是 jest 发出了 2 个不同的请求(一个用于登录,另一个用于创建项目),或者会话不会持续到同一个请求中?

中间件看起来像这样:

exports.isAuth = (req,res,next) => {
    if(!req.session.isAuth) {
       return res.status(401).json({ message: 'You cannot take this action,please login' });
    }
}

然后我的路线看起来像这样:

// isAuth.isAuth is the middleware that checks the session

router.put('/auth/api/sell',isAuth.isAuth,authController.createItem);

测试如下:

const supertest = require('supertest');
const request = supertest(app); // I exported app so that is not listening to any port at 
                               // the time that I attach it to supertest

// I first have these 2 functions
function put(url,body) {
    const httpRequest = request.put(url);
    httpRequest.send(body);
    httpRequest.set('Accept','application/json');
    httpRequest.set('Origin',process.env.LOCALHOST_BE);
    return httpRequest;
};

function post(url,body) {
    const httpRequest = request.post(url);
    httpRequest.send(body);
    httpRequest.set('Accept',process.env.LOCALHOST_BE);
    return httpRequest;
}; 

describe('create item',() => {
beforeEach(async (done) => {
    // these lines are needed in order to mock the verify token function
    const jwtSpy = jest.spyOn(jwt,'verify');
    jwtSpy.mockReturnValue('some decoded token');

    await post('/auth/api/login',{ email: 'test@test.com',password: '123456' });
    done();
});

    it('creates an item if all the inputs are correct',async (done) => {

    try {
        const reqItems = {
            body: {
                title: 'test',description: 'testing',image: 'https://res.cloudinary.com/dqhw3ma9u/image/upload/v1615827298/my-shop/before_after_analogy_rtkuec_vg8y7d.png',price: 10,stock: 1,}
        };  

        const response = await put('/auth/api/sell',reqItems.body);
        expect(response.body.message).toBe('item create');
        done();

    } catch (err) {
        console.log(err);
        done();
    }
});

我尝试了以下方法但没有成功:

const request = require('super-request');

request(app)
    .post('/auth/api/login')
    .form({ email: 'test@test.com',password: '123456' }) // I also tried auth and send
    .set('Accept','application/json')
    .set('Origin',process.env.LOCALHOST_BE)
    .end()

    .put('/auth/api/sell')
    .form(req.body) // I also tried auth and send
    .set('Accept',process.env.LOCALHOST_BE)
    .expect(200,"item create") 
    .end(function(err){
        if(err){
            throw err;
        }
})

还有:

supertest.agent(app)
    .post('/auth/api/login')
    .send({ email: 'test@test.com',password: '123456' })
    .expect(200)
    .end(function (err,res) {
        if(err) return done(err)
    })

supertest.agent(app)
    .put('/auth/api/sell')
    .send(reqItems.body)
    .expect(200)
    .end(function (err,res) {
        if(err) return done(err)
    })

也在不同的文件 (loginFunctionTest) 中我有这个(我确信它不会解决问题,但我还是尝试了):

const superagent = require('superagent');

const agent = superagent.agent();

exports.login = function (request,done) {
request
    .post('/auth/api/login')
    .send({ email: 'test@test.com',password: '123456' })
    .end(function (err,res) {
        if(err) {
            throw err;
        }
        agent.saveCookies(res);
        done(agent);
    });
};

然后在测试中我有这个(进入 beforeEach):

const login = require('./loginFunctionTest');

let agent;

    login.login(request,function (loginAgent) {
        agent = loginAgent;
        done();
    }); 
    done();

我也试过:

global.req = jest.fn(() => Promise.resolve({ session: { isAuth: true } }));

还有:

const session = require('supertest-session');
const app = path to app

let testSession = null;

testSession = session(app);

let authenticatedSession;

testSession.post('/auth/api/login')
    .send({ email: 'test@test.com',password: '123456' })
    .expect(200)
    .end(function (err) {
        if(err) return done(err);
        authenticatedSession = testSession;
        return done();
    })

authenticatedSession.put('/auth/api/sell') // here I get Cannot read property 'put' of undefined
    .send(reqItems.body)
    .expect(200)
    .end(function (err,res) {
        if(err) return done(err)
        expect(res.body.message).toBe('created')
    })

和(即使这样做没有任何意义,因为它与现在的测试相同):

request
    .post('/auth/api/login')
    .set('Accept',process.env.LOCALHOST_BE)
    .send({ email: 'test@test.com',password: '123456' })
    .then(() => {
        request
            .put('/auth/api/sell')
            .set('Accept','application/json')
            .set('Origin',process.env.LOCALHOST_BE)
            .send(reqItems.body)
            .expect(200,done)
    })

解决方法

因此,为了解决这个问题,我做了以下操作(如果您按照文档进行操作很容易):

    const expressRequestMock = require('express-request-mock');
    const authController = require('../controllers/auth');

    it('creates an item if all the inputs are correct',async (done) => {

    try {
         // these are the data that I need for my middleware to work
        // you could have different data
        const decorators = { 
            session: { 
                isAuth: true,user: {
                    _id: '602fb86391feb44b24d37c28',}
            },body: {
                title: 'test',description: 'testing',image: 'https://res.cloudinary.com/dqhw3ma9u/image/upload/v1615827298/my-shop/before_after_analogy_rtkuec_vg8y7d.png',price: 10,stock: 1,}
        };

        const { res } = await expressRequestMock(authController.createItem,decorators);
        expect(res.statusCode).toBe(200); // I tried different inputs and it works with 
                                      // every codes,the message is not available though
        done();

    } catch (err) {
        console.log(err);
        done(err); // if u do only done() test will pass even though it should fail
    }
});

可以找到模块文档here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...