NodeJS 如何在express中间件(express-validator/mocha/chai/sinon/proxyquire)中消除依赖关系

ukxgm1gy  于 2023-01-30  发布在  Node.js
关注(0)|答案(1)|浏览(117)

****编辑:**用一个简单的例子重写,首先:

我有一个测试文件和两个模块。
moduleA具有相关性moduleB

// moduleA.js
const ModuleB = require('./moduleB');

function functionA() {
  return 20 + ModuleB.functionB();
};

module.exports = { functionA };

// moduleB.js
const functionB = () => {
  return 10;
}

module.exports = { functionB }

我的测试文件使用proxyquire存根出functionB(从moduleB返回):

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

describe('Unit Tests', function() {
  it('should work', () => {
    const mockedFn = sinon.stub();
    mockedFn.returns(30);

    const copyModuleA = proxyquire('./moduleA', {
      './moduleB': {
        functionB: mockedFn
      }
    });

    console.log(copyModuleA.functionA());
  })
});

因此它输出50(存根函数B 30 +函数A 20
现在我尝试将这个例子应用到我的代码中:
moduleA在这里是一个名为validation.js的文件,它依赖于moduleB,在这里是一个sequelize模型Person,它有我想要模拟的函数:findOne
validation.js导出module.exports = { validateLogin };,这是一个调用validate的函数,validate返回使用Person.findOne()的函数
所以在我看来,就像这个简单的例子一样,我需要创建一个存根,指向proxyquire中的验证模块,并引用依赖项及其findOne函数,如下所示:

const stubbedFindOne = sinon.stub();
stubbedFindOne.resolves();
validationModule = proxyquire('../../utils/validation', {
  '../models/Person': {
    findOne: stubbedFindOne
  }
});

这个 * 应该 * 在validation.js中stub Person.findOne。但是看起来没有。我不知道为什么。

let validationModule;

describe('Unit Tests', () => {
  before(() => {
    const stubbedFindOne = sinon.stub();
    stubbedFindOne.resolves();
    validationModule = proxyquire('../../utils/validation', {
      '../models/Person': {
        findOne: stubbedFindOne
      }
    });

  }) 
  it.only('should return 422 if custom email validation fails', async() => {

    const wrongEmailReq = { body: {email: 'nik@hotmail.com'} };

    const res = {
      statusCode: 500,
      status: (code) => {this.statusCode = code; return this},
    };
  
    const validationFn = validationModule.validateLogin();
    const wrongEmail = await validationFn(wrongEmailReq, res, ()=>{});

    expect(wrongEmail.errors[0].msg).to.be.equal('Custom Authorisation Error');

    return;
  })

这是我的validation.js文件:

const Person = require('../models/Person');

// parallel processing
const validate = validations => {
  return async (req, res, next) => {
    await Promise.all(validations.map(validation => validation.run(req)));

    const errors = validationResult(req);
    if (errors.isEmpty()) {
      return next();
    }

    const error = new Error();
    error.message = process.env.NODE_ENV === 'development'? 'Validation Failed':'Error';

    error.statusCode = !errors.isEmpty()? 422:500;
    error.errors = errors.array({onlyFirstError: true});
    next(error);
    return error;
  };
};

const validateLogin = () => {
  const validations = [
    body('email')
    .isString()
    // snip
    .custom(async (value, {req}) => {
        try{
            const person = await Person.findOne({ where: { email: value } });
            
            if(!person) return Promise.reject('Custom Authorisation Error'); 

        } catch(err) {
          throw err;
        }
    })
    .trim(),
  ];

  return validate(validations);
}

module.exports = {
  validateLogin
};
5vf7fwbs

5vf7fwbs1#

因此,除了我对函数的存根处理方式不同之外,小示例和我的应用程序中的代码都是正确的,它不应该是resolvereject(我绝望地尝试了这两种方法),它应该返回null以满足条件,而不是跳转到catch块:

try{
        const person = await Person.findOne({ where: { email: value } });
        
        if(!person) return Promise.reject('Custom Authorisation Error'); 

    } catch(err) {
      throw err;
    }

希望这个简单的例子对其他使用proxyquire的人有所帮助

相关问题