【问题标题】:Redis mock in nodejs cannot stub non-existent property createClientnodejs中的Redis模拟不能存根不存在的属性createClient
【发布时间】:2020-11-04 15:23:18
【问题描述】:

我在尝试使用 mocha 和 sinon 在 NodeJS 中模拟 redis createClient() 方法时遇到问题。这是我的 index.js 的 sn-p。在socket类里面,有一个create redis连接。现在在我的单元测试中,我遇到了这个错误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()
      })
    })
  })
})

【问题讨论】:

    标签: javascript node.js unit-testing redis sinon


    【解决方案1】:

    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 |                   
    ----------|---------|----------|---------|---------|-------------------
    

    【讨论】:

      猜你喜欢
      • 2020-03-10
      • 1970-01-01
      • 2021-01-07
      • 2016-05-30
      • 2019-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多