首页 > 解决方案 > 如何模拟单元测试redis助手是任何if else语句

问题描述

我有这样的代码

const client = redis.createClient({
      retry_strategy: function (options) {
        if (options.error) {
          if (options.error.code === 'ECONNREFUSED') {
            // End reconnecting on a specific error
            // and flush all commands with a individual errors
            logger.log('redis', 'The server refused the connection', 'error');
            return new Error('The server refused the connection');
          }
          if (options.error.code === 'ECONNRESET') {
            logger.log('redis', 'The server reset the connection', 'error');
            return new Error('The server reset the connection');
          }
          if (options.error.code === 'ETIMEDOUT') {
            logger.log('redis', 'The server timeouted the connection', 'error');
            return new Error('The server timeouted the connection');
          }
        }
        if (options.total_retry_time > 1000 * 60 * 60) {
          // End reconnecting after a specific timeout and flush all commands
          // with a individual error
          logger.log('redis', 'Retry time exhausted', 'error');
          return new Error('Retry time exhausted');
        }
        if (options.attempt > 10) {
          // End reconnecting with built in error
          logger.log('redis', 'Retry attempt exceed', 'error');
          return undefined;
        }
        // reconnect after
        return Math.min(options.attempt * 100, 3000);
      },
      ...config,
    });

我已经进行了单元测试,但显然没有太多处理所有事情,如果在上面的代码中出现其他情况,如何处理语句

我的单元测试是这样的

sinon.stub(redis, 'createClient').resolves({err: true});
const res = await connection.createConnectionPool(config);
redis.createClient.restore();

如何为此创建单元测试?

标签: javascriptnode.jsunit-testingsinonnode-redis

解决方案


这是单元测试解决方案:

index.js

const redis = require('redis');

const logger = {
  log: console.log,
};

const client = redis.createClient({
  retry_strategy: function(options) {
    if (options.error) {
      if (options.error.code === 'ECONNREFUSED') {
        logger.log('redis', 'The server refused the connection', 'error');
        return new Error('The server refused the connection');
      }
      if (options.error.code === 'ECONNRESET') {
        logger.log('redis', 'The server reset the connection', 'error');
        return new Error('The server reset the connection');
      }
      if (options.error.code === 'ETIMEDOUT') {
        logger.log('redis', 'The server timeouted the connection', 'error');
        return new Error('The server timeouted the connection');
      }
    }
    if (options.total_retry_time > 1000 * 60 * 60) {
      logger.log('redis', 'Retry time exhausted', 'error');
      return new Error('Retry time exhausted');
    }
    if (options.attempt > 10) {
      logger.log('redis', 'Retry attempt exceed', 'error');
      return undefined;
    }
    return Math.min(options.attempt * 100, 3000);
  },
});

module.exports = client;

index.test.js

const sinon = require('sinon');
const redis = require('redis');

describe('61096134', () => {
  let logSpy;
  beforeEach(() => {
    logSpy = sinon.spy(console, 'log');
  });
  afterEach(() => {
    sinon.restore();
    delete require.cache[require.resolve('./')];
  });
  it('should return an error if server refused the connection', () => {
    const options = { error: { code: 'ECONNREFUSED' } };
    let returnValue;
    const createClientStub = sinon.stub(redis, 'createClient').callsFake((clientOpts) => {
      returnValue = clientOpts.retry_strategy(options);
    });
    require('./');
    sinon.assert.match(returnValue.message, 'The server refused the connection');
    sinon.assert.calledWithExactly(createClientStub, { retry_strategy: sinon.match.func });
    sinon.assert.calledWithExactly(logSpy, 'redis', 'The server refused the connection', 'error');
  });
  it('should return an error if server reset the connection', () => {
    const options = { error: { code: 'ECONNRESET' } };
    let returnValue;
    const createClientStub = sinon.stub(redis, 'createClient').callsFake((clientOpts) => {
      returnValue = clientOpts.retry_strategy(options);
    });
    require('./');
    sinon.assert.match(returnValue.message, 'The server reset the connection');
    sinon.assert.calledWithExactly(createClientStub, { retry_strategy: sinon.match.func });
    sinon.assert.calledWithExactly(logSpy, 'redis', 'The server reset the connection', 'error');
  });

  it('should return an error if server timeouted the connection', () => {
    const options = { error: { code: 'ETIMEDOUT' } };
    let returnValue;
    const createClientStub = sinon.stub(redis, 'createClient').callsFake((clientOpts) => {
      returnValue = clientOpts.retry_strategy(options);
    });
    require('./');
    sinon.assert.match(returnValue.message, 'The server timeouted the connection');
    sinon.assert.calledWithExactly(createClientStub, { retry_strategy: sinon.match.func });
    sinon.assert.calledWithExactly(logSpy, 'redis', 'The server timeouted the connection', 'error');
  });

  it('should return an error if retry time exhausted', () => {
    const options = { total_retry_time: 1000 * 60 * 61 };
    let returnValue;
    const createClientStub = sinon.stub(redis, 'createClient').callsFake((clientOpts) => {
      returnValue = clientOpts.retry_strategy(options);
    });
    require('./');
    sinon.assert.match(returnValue.message, 'Retry time exhausted');
    sinon.assert.calledWithExactly(createClientStub, { retry_strategy: sinon.match.func });
    sinon.assert.calledWithExactly(logSpy, 'redis', 'Retry time exhausted', 'error');
  });

  it('should return undefined if retry attempt exceed', () => {
    const options = { attempt: 11 };
    let returnValue;
    const createClientStub = sinon.stub(redis, 'createClient').callsFake((clientOpts) => {
      returnValue = clientOpts.retry_strategy(options);
    });
    require('./');
    sinon.assert.match(returnValue, undefined);
    sinon.assert.calledWithExactly(createClientStub, { retry_strategy: sinon.match.func });
    sinon.assert.calledWithExactly(logSpy, 'redis', 'Retry attempt exceed', 'error');
  });

  it('should return retry stragegy', () => {
    const options = { attempt: 5 };
    let returnValue;
    const createClientStub = sinon.stub(redis, 'createClient').callsFake((clientOpts) => {
      returnValue = clientOpts.retry_strategy(options);
    });
    require('./');
    sinon.assert.match(returnValue, 500);
    sinon.assert.calledWithExactly(createClientStub, { retry_strategy: sinon.match.func });
  });
});

带有覆盖率报告的单元测试结果:

  61096134
redis The server refused the connection error
    ✓ should return an error if server refused the connection (945ms)
redis The server reset the connection error
    ✓ should return an error if server reset the connection
redis The server timeouted the connection error
    ✓ should return an error if server timeouted the connection
redis Retry time exhausted error
    ✓ should return an error if retry time exhausted
redis Retry attempt exceed error
    ✓ should return undefined if retry attempt exceed
    ✓ should return retry stragegy


  6 passing (1s)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |    91.67 |     100 |     100 |                   
 index.js |     100 |    91.67 |     100 |     100 | 18                
----------|---------|----------|---------|---------|-------------------

源代码:https ://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/61096134


推荐阅读