2017-05-28 164 views
0

目前我處理我的認證如下:節點貓鼬摩卡:如何在我的測試處理Promise.reject

function login(req, res, next) { 
    // fetch user from the db 
    User.findOne(req.body) 
    .exec() // make query a Promise 
    .then((user) => { 
     const token = jwt.sign({ username: user.username }, config.jwtSecret); 
     return res.json({ token, username: user.username }); 
    }) 
    .catch(() => { 
     const err = new APIError('Authentication error', httpStatus.UNAUTHORIZED, true); 
     return Promise.reject(err); 
    }); 
} 

我想有一個共同的APIERROR類

import httpStatus from 'http-status'; 

/** 
* @extends Error 
*/ 
class ExtendableError extends Error { 
    constructor(message, status, isPublic) { 
    super(message); 
    this.name = this.constructor.name; 
    this.message = message; 
    this.status = status; 
    this.isPublic = isPublic; 
    this.isOperational = true; // This is required since bluebird 4 doesn't append it anymore. 
    Error.captureStackTrace(this, this.constructor.name); 
    } 
} 

/** 
* Class representing an API error. 
* @extends ExtendableError 
*/ 
class APIError extends ExtendableError { 
    /** 
    * Creates an API error. 
    * @param {string} message - Error message. 
    * @param {number} status - HTTP status code of error. 
    * @param {boolean} isPublic - Whether the message should be visible to user or not. 
    */ 
    constructor(message, status = httpStatus.INTERNAL_SERVER_ERROR, isPublic = false) { 
    super(message, status, isPublic); 
    } 
} 

export default APIError; 
規範我的錯誤

如何在我的測試中測試Promise.reject?

describe('# POST /api/v1/auth/login',() => { 
it('should return Authentication error',() => { 
    return request(app) 
    .post('/api/v1/auth/login') 
    .send(invalidUserCredentials) 
    // following lines are not valid anymore with Promise.reject .. 
    .expect(httpStatus.UNAUTHORIZED) 
    .then((res) => { 
     expect(res.body.message).to.equal('Authentication error'); 
    }); 
}); 

回答

1

您根本沒有處理錯誤/拒絕。您需要發送錯誤返回。我建議在express的路由末尾添加一個錯誤處理中間件,然後使用next(err)傳遞給它。

// at the end of your routes 
app.use(function(err, req, res, next) { 
    // do whatever you want, but at least send status and message: 
    res.status(err.status).json({ 
     message: err.message, 
    }); 
}); 

現在經過處理錯誤在你的路線:

.catch(() => { 
    const err = new APIError('Authentication error', httpStatus.UNAUTHORIZED, true); 
    return next(err); 
}); 
+0

感謝您的反饋很多約翰內斯..你把我的軌道。作爲事實上,我處理我express.js文件中的錯誤。但是內接縫的APIERROR設置不正確... const err = new APIError('Authentication error',httpStatus.UNAUTHORIZED,true); ('CTLR err instanceof APIError?:',(err instanceof APIError)); return next(err); err未設置爲APIError類實例...將檢查爲什麼... – erwin

+0

現在解決了......感謝Johannes ..我現在正確地在我的express.js error_handler中處理了錯誤..需要檢查與錯誤包使用!應該是es6錯誤,否則Babel不能正確處理instanceOf() – erwin

0

它現在運行良好,我在我的express.js錯誤處理的問題。作爲APIERROR類型檢查總是假的。 ..延長器ES6錯誤包,而不是錯誤解決這個問題通天...

APIError.js

import ExtendableError from 'es6-error'; // solve Babel issue w isInstanceOf() 
import httpStatus from 'http-status' 

class MyExtendableError extends ExtendableError { 
    constructor(message, status, isPublic) { 
    super(message); 
    this.name = this.constructor.name; 
    this.message = message; 
    this.status = status; 
    this.isPublic = isPublic; 
    this.isOperational = true; // This is required since bluebird 4 doesn't append it anymore. 
    Error.captureStackTrace(this, this.constructor.name); 
    } 
} 

/** 
* Class representing an API error. 
* @extends MyExtendableError 
*/ 
class APIError extends MyExtendableError { 
    constructor(message, status = httpStatus.INTERNAL_SERVER_ERROR, isPublic = false) { 
    super(message, status, isPublic); 
    } 
} 

export default APIError; 

Express.js

// catch 404 and forward to error handler 
/* istanbul ignore next */ 
app.use((req, res, next) => { 
    const err = new APIError('API not found', httpStatus.NOT_FOUND); 
    return next(err); 
}); 

// if error is not an instance Of APIError, convert it. 
app.use((err, req, res, next) => { 
    if (err instanceof expressValidation.ValidationError) { 
    // validation error contains errors which is an array of error each containing message[] 
    const unifiedErrorMessage = err.errors.map((error) => { 
     return error.messages.join('. '); 
    }).join(' and '); 
    const error = new APIError(unifiedErrorMessage, err.status, true); 
    res.status(error.status).json({ 
     message: err.isPublic ? err.message : httpStatus[err.status], 
     stack: (config.env === 'test' || config.env === 'development') ? err.stack : {} 
    }); 
    } else if (!(err instanceof APIError)) { 
    const apiError = new APIError(err.message, err.status, err.isPublic); 
    res.status(apiError.status).json({ 
     message: err.isPublic ? err.message : httpStatus[err.status], 
     stack: (config.env === 'test' || config.env === 'development') ? err.stack : {} 
    }); 
    }else { 
    res.status(err.status).json({ 
    message: err.isPublic ? err.message : httpStatus[err.status], 
    stack: (config.env === 'test' || config.env === 'development') ? err.stack : {} 
    }); 
    } 
}); 

auth.route.js

import express from 'express'; 
import validate from 'express-validation'; 
import expressJwt from 'express-jwt'; 
import paramValidation from '../../../config/param-validation'; 
import authCtrl from '../controllers/auth.controller'; 
import config from '../../../config/config'; 

const router = express.Router(); 

/** POST /api/auth/login - Returns token if correct username and password is provided */ 
router.route('/login') 
    .post(validate(paramValidation.login), authCtrl.login); 

auth.controller.js

function login(req, res, next) { 
    // fetch user from the db 
    User.findOne(req.body) 
    .exec() // make query a Promise 
    .then((user) => { 
     const token = jwt.sign({ username: user.username }, config.jwtSecret); 
     return res.json({ token, username: user.username }); 
    }) 
    .catch(() => { 
     const err = new APIError('Authentication error', httpStatus.UNAUTHORIZED, true); 
     return next(err); 
    }); 
} 

auth.test.js

.. 
    it('should return Authentication error',() => { 
     return request(app) 
     .post('/api/v1/auth/login') 
     .send(invalidUserCredentials) 
     .expect(httpStatus.UNAUTHORIZED) 
     .then((res) => { 
      expect(res.body.message).to.equal('Authentication error'); 
     }); 
    }); 
...