存根没有在 .then() 内部被调用
Stub not getting called inside .then()
我正在对 Express 应用程序进行单元测试。我正在尝试模拟我的外部依赖项(Express、数据库等)并且接近突破。
但是,我遇到的问题是存根未从我的业务逻辑中的 .then()
中调用。
我尝试测试的几个方法如下:
/**
* Ping
* A simple endpoint to poke for testing.
* @arg {*} request - Incoming request
* @arg {*} response - Outgoing response
* @arg {*} next - Next route in series
*/
ping: (request, response, next) => {
let elapsed = Date.now() - request.start;
response.status(200).json({
request_started: new Date(request.start).toISOString(),
request_duration: `${elapsed} milliseconds`
});
},
/**
* Registration
* Allows for registration of a user name and password.
* @arg {*} request - Incoming request
* @arg {*} response - Outgoing response
* @arg {*} next - Next route in series
*/
register: (request, response, next) => {
let username = request.body.username;
let password = request.body.password;
this.model.registerUser(username, password).then(ret => {
if (ret) {
response.status(201).send("Created");
} else {
response.status(400).send("Error processing registration request. Please try again.");
}
}).catch(err => {
response.status(400).send("Error processing registration request. Please try again.");
});
}
register
returns 中的模型 Promise
包装对数据库的调用并根据结果进行回复。我有一个这个设置的模拟如下:
mockModel: {
registerUser: sinon.stub().callsFake(function(user, pass) {
if (typeof user !== 'undefined') {
return Promise.resolve(pass === 'pass');
}
}),
getUser: sinon.stub().callsFake(function(user, pass) {
if (typeof user !== 'undefined' && pass === 'pass') {
return Promise.resolve({id: 9999});
} else {
return Promise.resolve(false);
}
})
}
我还模拟了 response
对象,因此我可以传入它并确定它是否被正确调用:
mockRes: () => {
return {
status: sinon.stub().returnsThis(),
send: sinon.stub(),
json: sinon.stub()
};
}
测试时出现问题:
describe('Register() method', function() {
this.beforeEach(function() {
req = mockReq(0, {}, {username: 'user', password: 'pass'});
res = mockRes();
base.BaseRoutes(router, null, base.methods, mockModel);
});
it('Returns a 201 Created message upon success', function() {
base.methods.register(req, res);
chai.expect(res.status).to.have.been.calledWith(201);
chai.expect(res.send).to.have.been.calledWith('Created');
});
});
此处测试失败,出现以下错误:
1) Base Methods
Register() method
Returns a 201 Created message upon success:
AssertionError: expected stub to have been called with arguments 201
at Context.<anonymous> (test\spec.js:50:50)
使用调试器单步执行表明正在调用该方法,但我遇到了这个错误。
同一套件中利用相同模拟 request/response 的其他测试正常工作,但它们不使用 Promise
调用(示例:ping() 方法)
我怀疑它与范围界定有关,但我不确定哪里出了问题。
运行这样多试几次后,发现不是作用域的问题,而是异步的问题。测试用例在 Promise
resolved/rejected 之前完成。
我缺少关闭循环的部分是我的 Express 路由处理程序需要 return 他们创建的 Promise
来处理数据库调用:
register: (request, response, next) => {
let username = request.body.username;
let password = request.body.password;
return this.model.registerUser(username, password).then((ret) => {
if (ret) {
response.status(201).send("Created");
} else {
response.status(400).send("Error processing registration request. Please try again.");
}
}, (err) => {
response.status(400).send("Error processing registration request. Please try again.");
});
},
然后测试,在 returned Promise
上执行我在 then()
中的断言:
it('Returns a 201 Created message upon success', function(done) {
base.methods.register(req, res).then(x => {
chai.expect(res.status).to.have.been.calledWith(201);
chai.expect(res.send).to.have.been.calledWith('Created');
}).then(done, done);
});
it('Returns a 400 message upon failure', function(done) {
req = mockReq(0, {}, {username: 'user', password: 'fail'});
base.methods.register(req, res).then(x => {
chai.expect(res.status).to.have.been.calledWith(400);
chai.expect(res.send).to.have.been.calledWith(sinon.match.string);
}).then(done, done);
虽然有将 Promise
传递给测试并在那里处理它的示例以及单独测试 Express 路由处理程序的示例,但我找不到将两者结合起来进行测试的示例。希望这对其他人有用。
我正在对 Express 应用程序进行单元测试。我正在尝试模拟我的外部依赖项(Express、数据库等)并且接近突破。
但是,我遇到的问题是存根未从我的业务逻辑中的 .then()
中调用。
我尝试测试的几个方法如下:
/**
* Ping
* A simple endpoint to poke for testing.
* @arg {*} request - Incoming request
* @arg {*} response - Outgoing response
* @arg {*} next - Next route in series
*/
ping: (request, response, next) => {
let elapsed = Date.now() - request.start;
response.status(200).json({
request_started: new Date(request.start).toISOString(),
request_duration: `${elapsed} milliseconds`
});
},
/**
* Registration
* Allows for registration of a user name and password.
* @arg {*} request - Incoming request
* @arg {*} response - Outgoing response
* @arg {*} next - Next route in series
*/
register: (request, response, next) => {
let username = request.body.username;
let password = request.body.password;
this.model.registerUser(username, password).then(ret => {
if (ret) {
response.status(201).send("Created");
} else {
response.status(400).send("Error processing registration request. Please try again.");
}
}).catch(err => {
response.status(400).send("Error processing registration request. Please try again.");
});
}
register
returns 中的模型 Promise
包装对数据库的调用并根据结果进行回复。我有一个这个设置的模拟如下:
mockModel: {
registerUser: sinon.stub().callsFake(function(user, pass) {
if (typeof user !== 'undefined') {
return Promise.resolve(pass === 'pass');
}
}),
getUser: sinon.stub().callsFake(function(user, pass) {
if (typeof user !== 'undefined' && pass === 'pass') {
return Promise.resolve({id: 9999});
} else {
return Promise.resolve(false);
}
})
}
我还模拟了 response
对象,因此我可以传入它并确定它是否被正确调用:
mockRes: () => {
return {
status: sinon.stub().returnsThis(),
send: sinon.stub(),
json: sinon.stub()
};
}
测试时出现问题:
describe('Register() method', function() {
this.beforeEach(function() {
req = mockReq(0, {}, {username: 'user', password: 'pass'});
res = mockRes();
base.BaseRoutes(router, null, base.methods, mockModel);
});
it('Returns a 201 Created message upon success', function() {
base.methods.register(req, res);
chai.expect(res.status).to.have.been.calledWith(201);
chai.expect(res.send).to.have.been.calledWith('Created');
});
});
此处测试失败,出现以下错误:
1) Base Methods
Register() method
Returns a 201 Created message upon success:
AssertionError: expected stub to have been called with arguments 201
at Context.<anonymous> (test\spec.js:50:50)
使用调试器单步执行表明正在调用该方法,但我遇到了这个错误。
同一套件中利用相同模拟 request/response 的其他测试正常工作,但它们不使用 Promise
调用(示例:ping() 方法)
我怀疑它与范围界定有关,但我不确定哪里出了问题。
运行这样多试几次后,发现不是作用域的问题,而是异步的问题。测试用例在 Promise
resolved/rejected 之前完成。
我缺少关闭循环的部分是我的 Express 路由处理程序需要 return 他们创建的 Promise
来处理数据库调用:
register: (request, response, next) => {
let username = request.body.username;
let password = request.body.password;
return this.model.registerUser(username, password).then((ret) => {
if (ret) {
response.status(201).send("Created");
} else {
response.status(400).send("Error processing registration request. Please try again.");
}
}, (err) => {
response.status(400).send("Error processing registration request. Please try again.");
});
},
然后测试,在 returned Promise
上执行我在 then()
中的断言:
it('Returns a 201 Created message upon success', function(done) {
base.methods.register(req, res).then(x => {
chai.expect(res.status).to.have.been.calledWith(201);
chai.expect(res.send).to.have.been.calledWith('Created');
}).then(done, done);
});
it('Returns a 400 message upon failure', function(done) {
req = mockReq(0, {}, {username: 'user', password: 'fail'});
base.methods.register(req, res).then(x => {
chai.expect(res.status).to.have.been.calledWith(400);
chai.expect(res.send).to.have.been.calledWith(sinon.match.string);
}).then(done, done);
虽然有将 Promise
传递给测试并在那里处理它的示例以及单独测试 Express 路由处理程序的示例,但我找不到将两者结合起来进行测试的示例。希望这对其他人有用。