Sinon stub out 模块的功能
Sinon stub out module's function
假设我这里有一个文件:
// a.js
const dbConnection = require('./db-connection.js')
module.exports = function (...args) {
return async function (req, res, next) {
// somethin' somethin' ...
const dbClient = dbConnection.db
const docs = await dbClient.collection('test').find()
if (!docs) {
return next(Boom.forbidden())
}
}
}
,db-connection.js
看起来像这样:
const MongoClient = require('mongodb').MongoClient
const dbName = 'test'
const url = process.env.MONGO_URL
const client = new MongoClient(url, { useNewUrlParser: true,
useUnifiedTopology: true,
bufferMaxEntries: 0 // dont buffer querys when not connected
})
const init = () => {
return client.connect().then(() => {
logger.info(`mongdb db:${dbName} connected`)
const db = client.db(dbName)
})
}
/**
* @type {Connection}
*/
module.exports = {
init,
client,
get db () {
return client.db(dbName)
}
}
并且我有一个测试将 find()
方法存根到 return 至少为真(为了测试 a.js
的 return 值是否为是的。我该怎么做?
单元测试策略是存根数据库连接,我们不需要连接真正的mongo数据库服务器。这样我们就可以运行在与外界环境隔离的环境中测试用例。
您可以使用 stub.get(getterFn) 为 dbConnection.db
getter 替换新的 getter。
因为 MongoDB 客户端初始化发生在您需要 db-connection
模块时。在需要 a
和 db-connection
模块之前,您应该从环境变量中为 MongoClient
提供正确的 URL。否则,MongoDB nodejs 驱动程序将抛出一个无效的 url 错误。
例如
a.js
:
const dbConnection = require('./db-connection.js');
module.exports = function () {
const dbClient = dbConnection.db;
const docs = dbClient.collection('test').find();
if (!docs) {
return true;
}
};
db-connection.js
:
const MongoClient = require('mongodb').MongoClient;
const dbName = 'test';
const url = process.env.MONGO_URL;
const client = new MongoClient(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const init = () => {
return client.connect().then(() => {
console.info(`mongdb db:${dbName} connected`);
const db = client.db(dbName);
});
};
module.exports = {
init,
client,
get db() {
return client.db(dbName);
},
};
a.test.js
:
const sinon = require('sinon');
describe('a', () => {
afterEach(() => {
sinon.restore();
});
it('should find some docs', () => {
process.env.MONGO_URL = 'mongodb://localhost:27017';
const a = require('./a');
const dbConnection = require('./db-connection.js');
const dbStub = {
collection: sinon.stub().returnsThis(),
find: sinon.stub(),
};
sinon.stub(dbConnection, 'db').get(() => dbStub);
const actual = a();
sinon.assert.match(actual, true);
sinon.assert.calledWithExactly(dbStub.collection, 'test');
sinon.assert.calledOnce(dbStub.find);
});
});
测试结果:
a
✓ should find some docs (776ms)
1 passing (779ms)
------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------|---------|----------|---------|---------|-------------------
All files | 75 | 50 | 25 | 75 |
a.js | 100 | 50 | 100 | 100 | 7
db-connection.js | 60 | 100 | 0 | 60 | 11-13,21
------------------|---------|----------|---------|---------|-------------------
假设我这里有一个文件:
// a.js
const dbConnection = require('./db-connection.js')
module.exports = function (...args) {
return async function (req, res, next) {
// somethin' somethin' ...
const dbClient = dbConnection.db
const docs = await dbClient.collection('test').find()
if (!docs) {
return next(Boom.forbidden())
}
}
}
,db-connection.js
看起来像这样:
const MongoClient = require('mongodb').MongoClient
const dbName = 'test'
const url = process.env.MONGO_URL
const client = new MongoClient(url, { useNewUrlParser: true,
useUnifiedTopology: true,
bufferMaxEntries: 0 // dont buffer querys when not connected
})
const init = () => {
return client.connect().then(() => {
logger.info(`mongdb db:${dbName} connected`)
const db = client.db(dbName)
})
}
/**
* @type {Connection}
*/
module.exports = {
init,
client,
get db () {
return client.db(dbName)
}
}
并且我有一个测试将 find()
方法存根到 return 至少为真(为了测试 a.js
的 return 值是否为是的。我该怎么做?
单元测试策略是存根数据库连接,我们不需要连接真正的mongo数据库服务器。这样我们就可以运行在与外界环境隔离的环境中测试用例。
您可以使用 stub.get(getterFn) 为 dbConnection.db
getter 替换新的 getter。
因为 MongoDB 客户端初始化发生在您需要 db-connection
模块时。在需要 a
和 db-connection
模块之前,您应该从环境变量中为 MongoClient
提供正确的 URL。否则,MongoDB nodejs 驱动程序将抛出一个无效的 url 错误。
例如
a.js
:
const dbConnection = require('./db-connection.js');
module.exports = function () {
const dbClient = dbConnection.db;
const docs = dbClient.collection('test').find();
if (!docs) {
return true;
}
};
db-connection.js
:
const MongoClient = require('mongodb').MongoClient;
const dbName = 'test';
const url = process.env.MONGO_URL;
const client = new MongoClient(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const init = () => {
return client.connect().then(() => {
console.info(`mongdb db:${dbName} connected`);
const db = client.db(dbName);
});
};
module.exports = {
init,
client,
get db() {
return client.db(dbName);
},
};
a.test.js
:
const sinon = require('sinon');
describe('a', () => {
afterEach(() => {
sinon.restore();
});
it('should find some docs', () => {
process.env.MONGO_URL = 'mongodb://localhost:27017';
const a = require('./a');
const dbConnection = require('./db-connection.js');
const dbStub = {
collection: sinon.stub().returnsThis(),
find: sinon.stub(),
};
sinon.stub(dbConnection, 'db').get(() => dbStub);
const actual = a();
sinon.assert.match(actual, true);
sinon.assert.calledWithExactly(dbStub.collection, 'test');
sinon.assert.calledOnce(dbStub.find);
});
});
测试结果:
a
✓ should find some docs (776ms)
1 passing (779ms)
------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------------|---------|----------|---------|---------|-------------------
All files | 75 | 50 | 25 | 75 |
a.js | 100 | 50 | 100 | 100 | 7
db-connection.js | 60 | 100 | 0 | 60 | 11-13,21
------------------|---------|----------|---------|---------|-------------------