我正在尝试使用带有promises的chai-http插件(使用q)。我正在为项目使用TypeScript。
/test/users.ts:
import "mocha";
import { Collection } from "mongodb";
import { Server } from "../app";
import { IUser } from "../interfaces/user";
import { IUserModel, User } from "../schemas/user";
//use q promises
global.Promise = require("q");
//import mongoose
import mongoose = require("mongoose");
//require http server
var http = require("http");
//require chai and use should assertions
let chai = require("chai");
let expect = chai.expect;
chai.should();
//configure chai-http
chai.use(require("chai-http"));
//create http server
var port = 8080;
var app = Server.bootstrap().app;
app.set("port", port);
var server = http.createServer(app);
server.listen(port);
//parent block
describe("UserApi", function() {
const BASE_URI: string = "/api/users";
const COLLECTION_NAME: string = "user";
var id: string;
before(function(done: MochaDone) {
//empty database
if (collectionExists(COLLECTION_NAME)) {
User.remove({}).catch(function(result: any) {
done(result);
});
}
//create a user
console.log("Creating a new user.");
var data: IUser = {
firstName: "Brian",
lastName: "Love",
email: "test@test.com"
};
new User(data).save().then(function(user: any) {
User.findOne(data).then(function(user: IUserModel) {
id = user.id;
done();
}).catch(function(result: any) {
done(result);
});
}).catch(function(result: any) {
done(result);
});
});
describe("/GET user", function() {
it("it should get a user", function() {
return chai
.request(server)
.get(`${BASE_URI}/${id}`)
.then(function(res: any) {
//this does not work:
expect(res).to.have.status(200);
//this does not work either:
//res.should.have.status(200);
});
});
});
});
function collectionExists(collectionName: string) {
return mongoose.connection.on("open", function() {
return mongoose.connection.db.listCollections({name: collectionName}).toArray().then(function(items: Collection[]) {
return (items.length > 0);
});
});
}
快速服务器在/app.ts中创建:
//import modules
import * as bodyParser from "body-parser";
import * as cookieParser from "cookie-parser";
import * as express from "express";
import * as http from "http";
import * as logger from "morgan";
import * as path from "path";
import * as expressSession from "express-session";
import * as url from "url";
import errorHandler = require("errorhandler");
import flash = require("connect-flash");
import methodOverride = require("method-override");
import passport = require("passport");
//import mongoose
import mongoose = require("mongoose");
//import config
import { ConfigurationFactory } from "./config/factory";
import { IConfiguration } from "./config/config";
/**
* The server.
*
* @class Server
*/
export class Server {
public app: express.Application;
/**
* Bootstrap the application.
*
* @class Server
* @method bootstrap
* @static
* @return {ng.auto.IInjectorService} Returns the newly created injector for this app.
*/
public static bootstrap(): Server {
return new Server();
}
/**
* Constructor.
*
* @class Server
* @constructor
*/
constructor() {
//create expressjs application
this.app = express();
//configure application
this.config();
//add routes
this.routes();
//add api
this.api();
}
public api() {
//code ommitted
}
/**
* Configure application
*
* @class Server
* @method config
* @return void
*/
public config() {
//get configuration
let configuration: IConfiguration = ConfigurationFactory.config();
console.log(`[Server.config] Environment: ${configuration.toString()}`);
//configure jade
this.app.set("views", path.join(__dirname, "views"));
this.app.set("view engine", "jade");
//mount logger
this.app.use(logger("dev"));
//mount json form parser
this.app.use(bodyParser.json());
//mount query string parser
this.app.use(bodyParser.urlencoded({
extended: true
}));
//mount cookie parker
this.app.use(cookieParser());
//mount override
this.app.use(methodOverride());
//add static paths
this.app.use(express.static(path.join(__dirname, "public")));
//connect to mongoose
mongoose.connect(configuration.db.mongodb).catch(error => new Error(error.message));
//use q library for mongoose promise
mongoose.Promise = require("q").Promise;
// catch 404 and forward to error handler
this.app.use(function(err: any, req: express.Request, res: express.Response, next: express.NextFunction) {
err.status = 404;
next(err);
});
//error handling
if (configuration.isDevelopment() || configuration.isTest()) {
this.app.use(errorHandler());
} else if (configuration.isProduction()) {
this.app.use(function(err: any, req: express.Request, res: express.Response, next: express.NextFunction) {
//set status
var status: number = err.status || 500;
res.status(status);
//render error
res.render("error", {
message: err.message,
error: err
});
});
}
}
/**
* Create and return Router.
*
* @class Server
* @method config
* @return void
*/
private routes() {
//code ommitted
}
}
我试图同时使用expect和should断言样式,但是我得到一个错误,表明结果没有" status"属性。检查 res 表示确实没有status属性。我能够在.then()匿名函数中设置断点。以下是显示res变量的屏幕截图:Screenshot of VS Code debug
运行mocha测试的例外是:
1) UserApi /GET user it should get a user:
AssertionError: expected [Function] to have a property 'status'
at Assertion.<anonymous> (node_modules/chai-http/lib/http.js:80:38)
at Assertion.ctx.(anonymous function) [as status] (node_modules/chai/lib/chai/utils/addMethod.js:41:25)
at dist/test/users.js:49:37
at _fulfilled (node_modules/q/q.js:834:54)
at self.promiseDispatch.done (node_modules/q/q.js:863:30)
at Promise.promise.promiseDispatch (node_modules/q/q.js:796:13)
at node_modules/q/q.js:857:14
at runSingle (node_modules/q/q.js:137:13)
at flush (node_modules/q/q.js:125:13)
我更愿意使用承诺方法。我检查了DefinitelyTyped定义文件,并且应该调用then()方法,第一个参数是ChaiHttp.Response类型。响应对象应该有3个属性:
interface Response {
body: any;
type: string;
status: number;
}
为什么我的&#34; res&#34;参数,应该是一个ChaiHttp.Response对象,不是吗?
答案 0 :(得分:1)
我想出了这个问题。我在mongoose中使用q库来承诺,我没有正确设置它。在阅读了更多文档后,我意识到您需要引用.Promise静态属性。花了很长时间才发现这一点,所以我希望这有助于拯救某人同样的问题。
以下是在mongoose中正确使用q for promises的代码:
//use q promises
global.Promise = require("q").Promise;
//import mongoose
import mongoose = require("mongoose");
//use q library for mongoose promise
mongoose.Promise = global.Promise;