我遇到了一个让我头疼的问题。我正在使用 passportJSpassport-facebook-token
以及passport-google-oauth20
在我的 node-express API 中使用 Facebook 和 Google 实现社交登录。
问题出现在单元测试中;我没有找到如何进行集成。
这是我尝试过的:
路线
router.post(
'/facebook',
passport.authenticate('facebook-token', { session: false }),
authCtrl.socialLogin,
);
router.post('/google', passport.authenticate('google', { session: false }), authCtrl.socialLogin);
该路线使用我配置如下的 passportJS 中间件:
passport.use(
'facebook-token',
new FacebookTokenStrategy(
{
clientID: FACEBOOK_APP_ID,
clientSecret: FACEBOOK_APP_SECRET,
},
async (_accessToken: string, _refreshToken: string, profile, done) => {
done(null, profile);
},
),
);
passport.use(
'google',
new GoogleStrategy(
{
clientID: GOOGLE_APP_ID,
clientSecret: GOOGLE_APP_SECRET,
},
async (_accessToken: string, _refreshToken: string, profile, done) => {
done(undefined, profile);
},
),
);
控制器
这是我的控制器的样子
public async socialLogin(req: Request, res: Response): Promise<any> {
try {
const { provider, displayName, emails, photos }: any = req.user;
const profile = {
username: displayName.replace(' ', '_').toLowerCase(),
email: emails ? emails[0].value : null,
image: photos[0].value,
};
console.log(req.user);
User.findOneAndUpdate(
{ 'profile.username': profile.username, 'profile.email': profile.email },
{ provider, profile, isLoggedIn: true, isAdmin: false },
{ new: true, upsert: true },
(err, data: any) => {
if (err) return helper.getServerError(res, err.message);
const { _id, profile, isAdmin } = data;
const { email } = profile;
const token = helper.generateToken({ _id, email, isAdmin });
return helper.getResponse(res, httpStatus.CREATED, { token, data });
},
);
return helper.getResponse(res, httpStatus.CREATED, { data: profile });
} catch (error) {
return helper.getServerError(res, error.message);
}
}
const { provider, displayName, emails, photos }: any = req.user;
简而言之,我必须从护照中间件方法user
自然返回的对象中接收提供者、显示名称、电子邮件和照片。authenticate()
你可以回顾一下路由定义来理解。
单元测试
当我使用 jest 对控制器进行单元测试时,我采用了模拟响应和请求的方法,以便可以将user
对象传递给请求。我尝试使用 jest 中的模拟实用程序,但无法正确模拟 express 请求和响应,因此尝试使用不同的第三方库,例如我觉得很有趣的 jest-express
这是我的测试的样子:
describe(Auth.prototype.socialLogin, () => {
let response: any;
let request: any;
beforeEach(() => {
response = new Response();
});
afterAll(() => {
response.resetMocked();
request.resetMocked();
});
it('should create a new user', async () => {
const requestMock: any = {
user: {
provider: 'facebook-token',
displayName: 'user name',
emails: [{ value: 'username@mail.com' }],
photos: [{ value: 'image.jpg' }],
},
};
request = new Request(requestMock);
await authCtrl.socialLogin(request, response);
expect(response.status).toHaveBeenCalledWith(201);
});
});
问题
当我运行测试时,我得到了这个响应。
它清楚地表明控制器正在运行,但它落在了假设以 500 状态响应表示错误请求的 catch 块上。
所以我真的需要帮助,如果有地方我做错了,或者有任何文档可以帮助我有效地模拟快速响应和请求。