为什么 sinon stub 没有替换实际的 exports.function
Why does sinon stub not replacing the actual exports.function
我有一个调用另一个异步导出函数的控制器异步函数,而不是测试依赖项我只想测试该依赖项函数的特定结果。但是,当我对函数进行 stub 时,什么也没有发生,return 结果就好像我一开始就没有对函数进行 stub 一样。
exports.getUser = async (req, res) => {
try {
let user = null;
if(req && req.params.id) {
const id = parseInt(req.params.id, 10);
if(isNaN(id)) {
return res.status(500).json({ message: 'Invalid request.' });
}
user = await userService.getUserById(id);
if(!products) {
return res.status(404).json({ message: `user does not exist for the given id` });
}
} else {
user = await userService.getUser();
if(!user || user.length === 0) {
return res.status(500).json({ message: 'user not available' });
}
}
res.jsonp({user});
} catch(e) {
return res.status(500).json({message: e.message});
}
}
现在我正在尝试对上述函数进行存根。但是我的存根不起作用。
测试文件:
const expect = require("chai").expect;
const request = require("supertest");
const server = require('../../server');
const sinon = require('sinon');
const userController = require('../../contollers/user');
describe('GET /v1/user', () => {
let userControllerStub;
beforeEach(() => {
userControllerStub = sinon
.stub(userController, 'getUser')
.resolves({getUser: [{ id: 123, name: 'xxxxx' }]});
})
afterEach(() => {
userControllerStub.restore();
});
it('Should return list of users', (done) => {
try {
request(server).get('/v1/user')
.end((err, res) => {
if (err) {
done(err);
}
console.log('res', res.body);
expect(res.statusCode).to.equal(200);
//expect(res.body.user).to.have.lengthOf(4); here i am expetcing stub should return the value
done();
});
} catch (err) {
done(err)
}
});
});
非常感谢任何帮助。
基于测试金字塔,我可以回答2级。
- 上下文单元测试。
我建议您先创建此测试,然后再进行下一步。您需要直接测试函数 getUser。当您测试该功能时,您需要存根 userService.getUserById 或 userService.getUser 取决于您的情况。
示例:
const sinon = require('sinon');
// Need to load user controller, the focus of the unit test.
const userController = require('../../controller/user');
// Need to load userServer for stub purpose.
// Note: I do not know whether this path is correct.
const userService = require('../../services/user');
describe('Controller User', function () {
describe('getUser', async function () {
it('with request param id', function () {
const stubUserServGetUserById = sinon.stub(userService, 'getUserById');
stubUserServGetUserById.resolves({ user: 'xxx' });
// Prepare the arguments.
const req = { params: { id: 1 } };
// Example: fake all resp. (or you can get the real resp)
const resp = {
status: sinon.fake(),
json: sinon.fake(),
jsonp: sinon.fake(),
};
// Called getUser directly.
const result = await userController.getUser(req, resp);
// Example: Expect the result.
expect(result).to.equal();
// Expect whether stub get called.
expect(stubUserServGetUserById.calledOnce).to.equal(true);
// Also you can validate whether fake function at resp get called if you need.
// Do not forget to restore the stub.
stubUserServGetUserById.restore();
});
it ('without request apram id', function () {
const stubUserServGetUser = sinon.stub(userController, 'getUser');
stubUserServGetUser.resolves({ user: 'xxx' });
// Prepare the arguments.
const req = { params: {} };
// Example: fake all resp. (or you can get the real resp)
const resp = {
status: sinon.fake(),
json: sinon.fake(),
jsonp: sinon.fake(),
};
// Called getUser directly.
const result = await userController.getUser(req, resp);
// Example: Expect the result.
expect(result).to.equal();
// Expect whether stub get called.
expect(stubUserServGetUser.calledOnce).to.equal(true);
// Also you can validate whether fake function at resp get called if you need.
// Do not forget to restore the stub.
stubUserServGetUser.restore();
});
});
});
- 上下文服务测试。
这正是您在上面的样本测试文件中试图做的。但是你需要知道,测试user v1服务不仅涉及控制器getUser,还涉及其他控制器,我不知道。在此测试级别,我建议您设置虚拟用户数据。测试前添加虚拟数据,测试后删除虚拟数据。然后添加验证控制器 getUser 是否被调用。或者,您可以将存根从 userController.getUser 更改为 userService.getUser(因为您知道 getUser 之前会根据单元测试被调用)。
这里没有样品。对不起。
希望对您有所帮助。
我有一个调用另一个异步导出函数的控制器异步函数,而不是测试依赖项我只想测试该依赖项函数的特定结果。但是,当我对函数进行 stub 时,什么也没有发生,return 结果就好像我一开始就没有对函数进行 stub 一样。
exports.getUser = async (req, res) => {
try {
let user = null;
if(req && req.params.id) {
const id = parseInt(req.params.id, 10);
if(isNaN(id)) {
return res.status(500).json({ message: 'Invalid request.' });
}
user = await userService.getUserById(id);
if(!products) {
return res.status(404).json({ message: `user does not exist for the given id` });
}
} else {
user = await userService.getUser();
if(!user || user.length === 0) {
return res.status(500).json({ message: 'user not available' });
}
}
res.jsonp({user});
} catch(e) {
return res.status(500).json({message: e.message});
}
}
现在我正在尝试对上述函数进行存根。但是我的存根不起作用。
测试文件:
const expect = require("chai").expect;
const request = require("supertest");
const server = require('../../server');
const sinon = require('sinon');
const userController = require('../../contollers/user');
describe('GET /v1/user', () => {
let userControllerStub;
beforeEach(() => {
userControllerStub = sinon
.stub(userController, 'getUser')
.resolves({getUser: [{ id: 123, name: 'xxxxx' }]});
})
afterEach(() => {
userControllerStub.restore();
});
it('Should return list of users', (done) => {
try {
request(server).get('/v1/user')
.end((err, res) => {
if (err) {
done(err);
}
console.log('res', res.body);
expect(res.statusCode).to.equal(200);
//expect(res.body.user).to.have.lengthOf(4); here i am expetcing stub should return the value
done();
});
} catch (err) {
done(err)
}
});
});
非常感谢任何帮助。
基于测试金字塔,我可以回答2级。
- 上下文单元测试。
我建议您先创建此测试,然后再进行下一步。您需要直接测试函数 getUser。当您测试该功能时,您需要存根 userService.getUserById 或 userService.getUser 取决于您的情况。
示例:
const sinon = require('sinon');
// Need to load user controller, the focus of the unit test.
const userController = require('../../controller/user');
// Need to load userServer for stub purpose.
// Note: I do not know whether this path is correct.
const userService = require('../../services/user');
describe('Controller User', function () {
describe('getUser', async function () {
it('with request param id', function () {
const stubUserServGetUserById = sinon.stub(userService, 'getUserById');
stubUserServGetUserById.resolves({ user: 'xxx' });
// Prepare the arguments.
const req = { params: { id: 1 } };
// Example: fake all resp. (or you can get the real resp)
const resp = {
status: sinon.fake(),
json: sinon.fake(),
jsonp: sinon.fake(),
};
// Called getUser directly.
const result = await userController.getUser(req, resp);
// Example: Expect the result.
expect(result).to.equal();
// Expect whether stub get called.
expect(stubUserServGetUserById.calledOnce).to.equal(true);
// Also you can validate whether fake function at resp get called if you need.
// Do not forget to restore the stub.
stubUserServGetUserById.restore();
});
it ('without request apram id', function () {
const stubUserServGetUser = sinon.stub(userController, 'getUser');
stubUserServGetUser.resolves({ user: 'xxx' });
// Prepare the arguments.
const req = { params: {} };
// Example: fake all resp. (or you can get the real resp)
const resp = {
status: sinon.fake(),
json: sinon.fake(),
jsonp: sinon.fake(),
};
// Called getUser directly.
const result = await userController.getUser(req, resp);
// Example: Expect the result.
expect(result).to.equal();
// Expect whether stub get called.
expect(stubUserServGetUser.calledOnce).to.equal(true);
// Also you can validate whether fake function at resp get called if you need.
// Do not forget to restore the stub.
stubUserServGetUser.restore();
});
});
});
- 上下文服务测试。
这正是您在上面的样本测试文件中试图做的。但是你需要知道,测试user v1服务不仅涉及控制器getUser,还涉及其他控制器,我不知道。在此测试级别,我建议您设置虚拟用户数据。测试前添加虚拟数据,测试后删除虚拟数据。然后添加验证控制器 getUser 是否被调用。或者,您可以将存根从 userController.getUser 更改为 userService.getUser(因为您知道 getUser 之前会根据单元测试被调用)。 这里没有样品。对不起。
希望对您有所帮助。