【问题标题】:How can I mock an imported dependency with express?如何使用 express 模拟导入的依赖项?
【发布时间】:2021-05-15 08:30:39
【问题描述】:

我正在对一个 express 函数进行单元测试。 express 函数使用我想模拟的导入(条带)。如何在使用 express 功能时模拟导入?问题是它是一个全局导入,如果我能以某种方式将它作为 express 函数的参数,我的问题就会得到解决。

表达代码(作为firebase_functions.subscribe导出到测试文件)

const functions = require('firebase-functions');
const stripe = require('stripe')(functions.config().stripe.client_id);

module.exports = async function( request, response ) {
  if( !request.query.id_token ) {
    response.status(400).json({message: 'id_token has not been provided'});
    return;
  }

  await admin.auth()
  .verifyIdToken( request.query.id_token )
  .then( id_token => {
    // pseudo-code: something is done with e.g. 
    const message = await stripe.xxx( id_token ); // returns 'some result I got using the stripe Mock in the process'
    response.status(200).json({message});
    return;
  })
  .catch( error => {
    return response.status(401).json({message: 'You are currently not logged in as an authorised user'});
  })
}

测试代码摘录

describe('subscribe( request, response)', () => {
  it( 'should redirect an user to an url for stripe subscriptions', async() => {
    // arrange
    const response = new ResponseSpy();
    const id_token = await get_id_token();
    const request = { query: { id_token }};
    // act
    await firebase_functions.subscribe( request, response );
    // assert
    assert.deepStrictEqual( result.json, {message: 'some result I got using the stripe Mock in the process'} );
  });
});

【问题讨论】:

    标签: node.js firebase unit-testing express stripe-payments


    【解决方案1】:

    由于您使用firebase-functions,您最好使用firebase-functions-test包来测试这些云功能。

    为了模拟独立函数stripe,您需要proxyquire 包。如需更多信息,请参阅How to use Link Seams with CommonJS

    我将使用sinon.js 作为存根库。而且,我将使用firebase-functions-test 包中的offline mode 来编写单元测试。

    这里是单元测试解决方案:

    index.js:

    const admin = require('firebase-admin');
    const app = admin.initializeApp();
    const functions = require('firebase-functions');
    const stripe = require('stripe')(functions.config().stripe.client_id);
    
    module.exports = async function (request, response) {
      if (!request.query.id_token) {
        response.status(400).json({ message: 'id_token has not been provided' });
        return;
      }
    
      await app
        .auth()
        .verifyIdToken(request.query.id_token)
        .then(async (id_token) => {
          const message = await stripe.xxx(id_token);
          response.status(200).json({ message });
          return;
        })
        .catch((error) => {
          return response.status(401).json({ message: 'You are currently not logged in as an authorised user' });
        });
    };
    

    index.test.js:

    const test = require('firebase-functions-test')();
    const admin = require('firebase-admin');
    test.mockConfig({ stripe: { client_id: 'client_123' } });
    const sinon = require('sinon');
    const proxyquire = require('proxyquire');
    
    describe('66157457', () => {
      afterEach(() => {
        sinon.restore();
      });
      it('should send message', async () => {
        const authStub = { auth: sinon.stub().returnsThis(), verifyIdToken: sinon.stub().resolves('token_123') };
        const adminInitStub = sinon.stub(admin, 'initializeApp').returns(authStub);
        const request = { query: { id_token: 'abc' } };
        const response = { status: sinon.stub().returnsThis(), json: sinon.stub() };
        const stripeStub = { xxx: sinon.stub().resolves('fake message') };
        const stripeFactory = sinon.stub().returns(stripeStub);
        const subscribe = proxyquire('./', {
          stripe: stripeFactory,
        });
        await subscribe(request, response);
        sinon.assert.calledOnce(adminInitStub);
        sinon.assert.calledWithExactly(stripeFactory, 'client_123');
        sinon.assert.calledOnce(authStub.auth);
        sinon.assert.calledWithExactly(authStub.verifyIdToken, 'abc');
        sinon.assert.calledWithExactly(stripeStub.xxx, 'token_123');
        sinon.assert.calledWithExactly(response.status, 200);
        sinon.assert.calledWithExactly(response.json, { message: 'fake message' });
        test.cleanup();
      });
    });
    

    单元测试结果:

      66157457
        ✓ should send message (145ms)
    
    
      1 passing (148ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |   76.92 |       50 |   66.67 |   76.92 |                   
     index.js |   76.92 |       50 |   66.67 |   76.92 | 8-9,21            
    ----------|---------|----------|---------|---------|-------------------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多