我正在学习测试,目前我使用jest
和supertest
来测试koa2
服务器,并且我测试的功能是登录,但是在测试时我总是收到false
登录功能,我发现require
经过长时间调试后在我的controllers/users.js
中返回了一个空对象,我不知道为什么,对此非常困惑,因为当我真正运行koa2服务器时一切正常,帮助,谢谢。
这是我的代码
user.spec.js
import server from "../../app.js"
import request from "supertest"
afterEach(() => {
server.close()
})
test("Failed to login if typing wrong name and password", async () => {
const response = await request(server)
.post("/auth/user")
.send({
name: "wrong",
password: "wrong"
})
expect(response.body.success).toBe(false)
})
test("Successed to login if typing right name and password", async () => {
const response = await request(server)
.post("/auth/user")
.send({
name: "rignt",
password: "right"
})
expect(response.body.success).toBe(true) // always received false
})
app.js
const Koa = require('koa')
const app = new Koa()
const router = require('koa-router')()
const bodyParser = require('koa-bodyparser')
const logger = require('koa-logger')
// const port = 4155
const port = 6155
const auth = require('./server/routes/auth')
const api = require('./server/routes/api')
const users = require('./server/models/users')
const path = require('path')
const serve = require('koa-static')
const mount = require('koa-mount')
const historyApiFallback = require('koa2-history-api-fallback')
// handle database
const objection = require('objection')
const Model = objection.Model
const Knex = require('knex')
const knexConfig = require('./server/config/knexfile')
// Initialize knex
const knex = Knex(knexConfig)
// Bind all Models to a knex instance
Model.knex(knex)
app.use(bodyParser())
app.use(logger())
app.use(async (ctx, next) => {
let start = new Date()
await next()
let ms = new Date() - start
console.log('%s %s - %s', ctx.method, ctx.url, ms)
})
app.on('error', (err, ctx) => {
console.log('server error', err)
})
// api for operate
router.use('/api', api.routes())
// auth for login
router.use('/auth', async (ctx, next) => {
let urlReg = /auth\/user$/
if(urlReg.test(ctx.url)) {
await next()
} else {
const { token } = ctx.request.body
if(global.userTokenObj[token] === undefined) {
const rs = await users.findToken(token)
if(rs.length > 0) {
global.userTokenObj[token] = 1
await next()
} else {
ctx.body = {
code: 1001,
msg: "no login"
}
}
} else {
await next()
}
}
})
router.use('/auth', auth.routes())
app.use(router.routes())
// avoid refesh 404
app.use(historyApiFallback())
// koa static
app.use(mount('/static', serve(path.resolve('static'))))
app.use(serve(path.resolve('dist')))
module.exports = app.listen(port, () => {
console.log(`Koa is listening in ${port}`)
})
// module.exports = app
routes / auth.js
const {
getUserInfo,
postUserAuth,
} = require('../controllers/users')
const {
postFileNode,
postReadFile,
postWriteFile,
postBuildCode,
postDownloadProject
} = require('../controllers/editCode')
const router = require('koa-router')()
router.get('/user/:id', getUserInfo)
router.post('/user', postUserAuth)
router.post('/fileNode', postFileNode)
router.post('/readFile', postReadFile)
router.post('/writeFile', postWriteFile)
router.post('/build', postBuildCode)
router.post('/download', postDownloadProject)
module.exports = router
controllers / users.js
const users = require('../models/users') **// return empty object**
const jwt = require('jsonwebtoken') **// return empty object**
global.userTokenObj = {};
const getUserInfo = async ctx => {
try {
const id = ctx.params.id
const result = await users.getUserById(id)
ctx.body = result
} catch (error) {
console.log(error)
ctx.body = `error is ${error} when get user info`
}
}
const postUserAuth = async ctx => {
try {
const data = ctx.request.body // post data from request.body
const userInfo = await users.getUserByName(data.name)
if (userInfo != null) {
if (userInfo.password != data.password) {
ctx.body = {
success: false,
code: 2,
info: 'wrong password'
}
} else {
const userToken = {
name: userInfo.username,
id: userInfo.id
}
const secret = 'autoactivity'
const token = jwt.sign(userToken, secret)
global.userTokenObj[token] = userInfo.id
const rs = await users.setTokenById(userInfo.id, token)
ctx.body = {
success: true,
code: 0,
info: 'OK',
token
}
}
} else {
ctx.body = {
success: false,
code: 1,
info: 'no users'
}
}
} catch (error) {
console.log(error)
ctx.body = `error is ${error} when post user auth`
}
}
module.exports = {
getUserInfo,
postUserAuth,
}
models / users.js
const Model = require('objection').Model
class Users extends Model {
// Table name is the only required property.
static get tableName () {
return 'users'
}
}
const getUserById = async id => {
try {
const userInfo = await Users.query().findById(id)
return userInfo
} catch (error) {
console.log(error)
return error
}
}
const getUserByName = async name => {
try {
const userInfo = await Users
.query()
.findOne({
username: name
})
return userInfo
} catch (error) {
console.log(error)
return error
}
}
const setTokenById = async (id, token) => {
try {
const result = Users
.query()
.update({token})
.where('id', id)
return result
} catch(error) {
return error
}
}
const findToken = async (token) => {
try {
const result = Users
.query()
.select()
.where('token', token)
return result
} catch(error) {
return error
}
}
module.exports = {
getUserById,
getUserByName,
setTokenById,
findToken
}
package.json
{
"name": "auto-activity",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "shangwenlong652 <dxcqcv@gmail.com>",
"private": true,
"scripts": {
"update": "gulp",
"debugnode": "nodemon --inspect-brk app.js",
"start": "nodemon app.js",
"devserver": "node app.js",
"dev": "node build/dev-server.js",
"server": "pm2 start app.js --name 'auto-activity'",
"server:test": "pm2 start app.js --name 'test-auto-activity'",
"showpm2": "pm2 show auto-activity",
"showpm2:test": "pm2 show test-auto-activity",
"savepm2": "pm2 save",
"logspm2": "pm2 logs",
"restartpm2": "pm2 restart auto-activity",
"restartpm2:test": "pm2 restart test-auto-activity",
"listpm2": "pm2 ls",
"stoppm2": "pm2 stop auto-activity",
"stoppm2:test": "pm2 stop test-auto-activity",
"delpm2": "pm2 delete auto-activity",
"delpm2:test": "pm2 delete test-auto-activity",
"server:dev": "nodemon app.js",
"newMigrate": "knex migrate:make add_name_date_type_to_projects --knexfile=./server/config/knexfile.js",
"migrate": "knex --knexfile=./server/config/knexfile.js migrate:latest",
"rollback": "knex --knexfile=./server/config/knexfile.js migrate:rollback",
"build": "node build/build.js",
"test": "jest --forceExit --runInBand"
},
"jest": {
"verbose": true,
"testURL": "http://localhost/",
"moduleFileExtensions": [
"js"
],
"transform": {
".*\\.(vue)$": "<rootDir>/node_modules/vue-jest",
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
},
"setupTestFrameworkScriptFile": "mock-local-storage",
"coverageDirectory": "coverage",
"collectCoverage": true,
"coverageReporters": [
"lcov",
"text"
],
"moduleNameMapper": {
"@/(.*)$": "<rootDir>/src/$1"
},
"snapshotSerializers": [
"<rootDir>/node_modules/jest-serializer-vue"
]
},
"dependencies": {
"archiver": "2.1.0",
"await-busboy": "^1.0.1",
"axios": "^0.16.2",
"graceful-fs": "^4.1.11",
"jsonwebtoken": "~8.3.0",
"knex": "~0.15.2",
"koa": "^2.3.0",
"koa-bodyparser": "^4.2.0",
"koa-logger": "^3.0.1",
"koa-mount": "~3.0.0",
"koa-router": "^7.2.1",
"koa-static": "~4.0.1",
"koa2-history-api-fallback": "0.0.5",
"lodash": "^4.17.4",
"mariasql": "^0.2.6",
"mysql": "^2.13.0",
"objection": "^0.8.5",
"recursive-copy": "^2.0.6",
"replacestream": "^4.0.3",
"rimraf": "^2.6.2",
"vue": "2.4.2",
"vue-codemirror": "^4.0.5",
"vue-color": "^2.4.0",
"vue-router": "^2.6.0",
"vue-tree-halower": "^1.5.4",
"vuetify": "^0.15.2",
"vuex": "^2.3.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "~6.26.3",
"babel-eslint": "^7.1.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "~23.4.2",
"babel-loader": "^7.1.1",
"babel-plugin-array-includes": "^2.0.3",
"babel-plugin-istanbul": "^4.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-object-assign": "^6.22.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"babel-runtime": "^6.26.0",
"chai": "^3.5.0",
"chalk": "^2.3.0",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"cross-env": "~5.2.0",
"cross-spawn": "^5.0.1",
"css-loader": "^0.28.0",
"cssnano": "^3.10.0",
"del": "^3.0.0",
"dotenv": "~6.0.0",
"eslint": "~5.2.0",
"eslint-config-standard": "^6.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-html": "^3.0.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^2.0.1",
"eventsource-polyfill": "^0.9.6",
"express": "~4.16.3",
"extract-text-webpack-plugin": "^2.0.0",
"file-loader": "^0.11.1",
"friendly-errors-webpack-plugin": "^1.1.3",
"gulp": "~4.0.0",
"gulp-decompress": "^2.0.1",
"html-webpack-plugin": "^2.28.0",
"http-proxy-middleware": "~0.18.0",
"inject-loader": "^3.0.0",
"jest": "~23.4.2",
"jest-serializer-vue": "~2.0.2",
"lolex": "^1.5.2",
"mock-local-storage": "^1.0.5",
"opn": "^5.1.0",
"optimize-css-assets-webpack-plugin": "^2.0.0",
"ora": "^1.2.0",
"pm2": "~3.0.3",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"sinon": "^2.1.0",
"sinon-chai": "^2.8.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"supertest": "~3.1.0",
"url-loader": "~1.0.1",
"vue-jest": "~2.6.0",
"vue-loader": "^12.1.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "2.4.2",
"vue-test-utils": "~1.0.0-beta.11",
"webpack": "^2.6.1",
"webpack-bundle-analyzer": "~2.13.1",
"webpack-dev-middleware": "^1.10.0",
"webpack-hot-middleware": "^2.18.0",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
.babelrc
{
"presets": [
["env", {
"modules": false,
"targets": {
"chrome": 42,
"firefox": 38,
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-runtime", "transform-vue-jsx"],
"env": {
"test": {
"presets": [["env", { "targets": { "node": "current" }} ]] ,
"plugins": [
"istanbul",
"transform-object-assign",
"array-includes",
"transform-runtime"
]
}
}
}
以及bitbutck
上的项目完整代码答案 0 :(得分:0)
您正在尝试在测试代码的第一行从app.js导入服务器!
import server from "../../app.js"
但是在app.js中,您没有导出服务器常量。将应用程序实例传递给 http.createServer()方法后,应该导出服务器。
const server = http.createServer(app);
module.exports = server;
然后它应该工作!