cookie 在 supertest/superagent 测试中持续存在,但用户不会保持登录状态

时间:2021-04-29 21:37:51

标签: node.js express jestjs passport.js superagent

我的目标

我试图在每次测试之前使用 supertest 的 agent 函数在玩笑 beforeEach() 中登录用户,因为我希望每个测试都在假设用户已登录的情况下运行。对于身份验证,我使用的是护照和本地护照。


这是我尝试过的(为了简洁起见,部分被剪掉了):

测试文件:

import { agent, SuperAgentTest } from 'supertest';
import app from '../../src/app';

// create a `testRequest` variable to use in the tests
// that will be refreshed in between
let testRequest: SuperAgentTest;

const fakeUser = { email: 'john@john', username: 'john', password: 'john' };

beforeEach(async () => {
  // create new agent
  testRequest = agent(app);

  // register and login
  await testRequest.post('/register').send(fakeUser).expect(302);

  // other irrelevant stuff...
});

// protected route
describe('POST /campgrounds/new', () => {
  it('returns 200 OK', () => {
    return testRequest.get('/campgrounds/new');
  })
});

/register 路线:

router.post('/register', async (req, res) => {
  const { password, ...details } = req.body;
  try {
    // I am using passport-local-mongoose for this function-
    // it just registers the user
    const user = await User.register(new User(details), password);
    req.login(user, (err) => {
      // error handling and redirect
    });
  } catch (e) {
    // error handling
  }
})

这是我的结果

我得到的不是 200 状态,而是 302 状态,这意味着我被重定向到登录页面。为了调试这个,我创建了一个名为 /current 的测试路由,它将记录当前用户和会话 ID cookie。然后,我分别在 GETit 函数中向此路由发送了 beforeEach 请求。

有趣的是,它们都记录了相同的会话 ID,但只有 beforeEach 中的请求附加了一个用户对象。

1 个答案:

答案 0 :(得分:2)

#1 确保正文解析器顺序正确

在任何路由或与身份验证相关的事情之前确保你有这个。

app.use(express.json())

#2 检查 Passport 中间件连接

确保在任何 app.use(passport.initialize())app.use(passport.session())app.use('/', aRouter) 等之前调用 router.getrouter.post

// Set up session w/ specific config
app.use(session({
  secret: 'bquyqueajhbd',
  resave: true,
  saveUninitialized: true,
  store: new FileStore({path: '/tmp/session'})
}));
// Wire up the 
app.use(passport.initialize())
app.use(passport.session())

编辑:关于req.user的注释

Passport 旨在将用户 ID 存储在会话中。

对服务器的每个请求都必须从数据库重新加载用户。 这是中间件 passport.initialize()passport.session() 的工作。

那里的逻辑将调用 passport.deserializeUser 以通过 ID 查找用户 - 与 passport.serializeUser 在登录会话时保存的 ID 相同。

passport.serializeUser(function(user, done) {
  done(null, user.id); // <-- Here's where the ID is saved to session.
});

passport.deserializeUser(function(id, done) {
  User.findById(id, function(err, user) {
    done(err, user); // <-- Here is where the `req.user` get's it's value from.
  });
});
<块引用>

为了调试这个,我将重点放在 passport.deserializeUser 回调上,在数据库查询之前和之后添加日志。

(注意:自从我教这个已经几年了。如果我没有使用准确的术语等,请见谅)