nodejs 中的 Redis 模拟无法存根不存在 属性 createClient
Redis mock in nodejs cannot stub non-existent property createClient
我在尝试使用 mocha 和 sinon 模拟 NodeJS 中的 redis createClient()
方法时遇到问题。这是我 index.js 的片段。在socketclass里面,有create redis connection。现在在我的单元测试中,我遇到了这个错误TypeError: Cannot stub non-existent property createClient
。我似乎无法弄清楚为什么?是因为模拟的某些顺序吗?
const express = require("express");
const http = require('http');
const redis = require('redis');
const expressApp = express();
const server = http.createServer(expressApp);
const io = require('socket.io')(server, {
pingInterval: 10000,
pingTimeout: 5000
});
const config = require('config');
const log = require('gelf-pro');
const HTTP_PORT = 3000;
// Socket IO call backs
io.on("connection", (client) => {
new Socket(client);
});
// export the server so it can be easily called for testing
exports.server = server.listen(HTTP_PORT, () => {
log.info('socketio server started at port ' + HTTP_PORT);
});
单元测试代码:
'use strict'
var expect = require('chai').expect
, redis = require('redis')
, redisMock = require('redis-mock')
, sinon = require('sinon')
, io = require('socket.io-client')
, ioOptions = {
transports: ['websocket']
, forceNew: true
, reconnection: false
}
, testMsg = JSON.stringify({message: 'HelloWorld'})
, sender
, receiver
describe('Chat Events', function(){
beforeEach(function(done){
sinon
.stub(redis.RedisClient.prototype, 'createClient')
.callsFake(function() {
console.log('mock redis called');
return redisMock.createClient();
});
// connect two io clients
sender = io('http://localhost:3000/', ioOptions)
receiver = io('http://localhost:3000/', ioOptions)
// finish beforeEach setup
done()
})
afterEach(function(done){
// disconnect io clients after each test
sender.disconnect()
receiver.disconnect()
done()
})
describe('Message Events', function(){
it('Clients should receive a message when the `message` event is emited.', function(done){
sender.emit('message', testMsg)
receiver.on('ackmessage', function(msg){
expect(msg).to.contains(testMsg)
done()
})
})
})
})
redis.createClient
方法是一个独立函数,不是 原型方法。如果您使用 TypeScript,我们可以检查 redis
包的类型。
index.d.ts
:
export function createClient(port: number, host?: string, options?: ClientOpts): RedisClient;
export function createClient(unix_socket: string, options?: ClientOpts): RedisClient;
export function createClient(redis_url: string, options?: ClientOpts): RedisClient;
export function createClient(options?: ClientOpts): RedisClient;
所以,你应该像这样存根:
index.js
:
const redis = require('redis');
function main() {
redis.createClient();
}
module.exports = main;
index.test.js
:
const main = require('./');
const redis = require('redis');
const sinon = require('sinon');
describe('62909606', () => {
it('should pass', () => {
const createClientStub = sinon.stub(redis, 'createClient').callsFake(function() {
console.log('mock redis called');
});
main();
sinon.assert.calledOnce(createClientStub);
});
});
带有覆盖率报告的单元测试结果:
62909606
mock redis called
✓ should pass
1 passing (9ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
我在尝试使用 mocha 和 sinon 模拟 NodeJS 中的 redis createClient()
方法时遇到问题。这是我 index.js 的片段。在socketclass里面,有create redis connection。现在在我的单元测试中,我遇到了这个错误TypeError: Cannot stub non-existent property createClient
。我似乎无法弄清楚为什么?是因为模拟的某些顺序吗?
const express = require("express");
const http = require('http');
const redis = require('redis');
const expressApp = express();
const server = http.createServer(expressApp);
const io = require('socket.io')(server, {
pingInterval: 10000,
pingTimeout: 5000
});
const config = require('config');
const log = require('gelf-pro');
const HTTP_PORT = 3000;
// Socket IO call backs
io.on("connection", (client) => {
new Socket(client);
});
// export the server so it can be easily called for testing
exports.server = server.listen(HTTP_PORT, () => {
log.info('socketio server started at port ' + HTTP_PORT);
});
单元测试代码:
'use strict'
var expect = require('chai').expect
, redis = require('redis')
, redisMock = require('redis-mock')
, sinon = require('sinon')
, io = require('socket.io-client')
, ioOptions = {
transports: ['websocket']
, forceNew: true
, reconnection: false
}
, testMsg = JSON.stringify({message: 'HelloWorld'})
, sender
, receiver
describe('Chat Events', function(){
beforeEach(function(done){
sinon
.stub(redis.RedisClient.prototype, 'createClient')
.callsFake(function() {
console.log('mock redis called');
return redisMock.createClient();
});
// connect two io clients
sender = io('http://localhost:3000/', ioOptions)
receiver = io('http://localhost:3000/', ioOptions)
// finish beforeEach setup
done()
})
afterEach(function(done){
// disconnect io clients after each test
sender.disconnect()
receiver.disconnect()
done()
})
describe('Message Events', function(){
it('Clients should receive a message when the `message` event is emited.', function(done){
sender.emit('message', testMsg)
receiver.on('ackmessage', function(msg){
expect(msg).to.contains(testMsg)
done()
})
})
})
})
redis.createClient
方法是一个独立函数,不是 原型方法。如果您使用 TypeScript,我们可以检查 redis
包的类型。
index.d.ts
:
export function createClient(port: number, host?: string, options?: ClientOpts): RedisClient;
export function createClient(unix_socket: string, options?: ClientOpts): RedisClient;
export function createClient(redis_url: string, options?: ClientOpts): RedisClient;
export function createClient(options?: ClientOpts): RedisClient;
所以,你应该像这样存根:
index.js
:
const redis = require('redis');
function main() {
redis.createClient();
}
module.exports = main;
index.test.js
:
const main = require('./');
const redis = require('redis');
const sinon = require('sinon');
describe('62909606', () => {
it('should pass', () => {
const createClientStub = sinon.stub(redis, 'createClient').callsFake(function() {
console.log('mock redis called');
});
main();
sinon.assert.calledOnce(createClientStub);
});
});
带有覆盖率报告的单元测试结果:
62909606
mock redis called
✓ should pass
1 passing (9ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------