【问题标题】:Mocking import with proxyquire works but stubbed function shows as not called使用 proxyquire 模拟导入有效,但存根函数显示为未调用
【发布时间】:2020-10-14 18:08:14
【问题描述】:

我有以下测试,我使用 proxyquire 来模拟 nodemailer,并让它的 createTransport 返回一个带有 sendMail 函数的对象,该函数是一个 sinon 存根。

   beforeEach(() => {
        sinonSandbox = createSandbox();
        sendMailMock = sinonSandbox.stub();
        mailService = proxyquire('../src/mailService',
            {
                'node-vault': () => { return { read: () => mockVaultData } },
                'nodemailer': {
                    createTransport: () => {
                        return {
                            sendMail: () => sendMailMock()
                        }
                    }
                }
            }
        )
       
        sinonSandbox.stub(vaultAuthAws.prototype, 'authenticate').returns(Promise.resolve(mockVaultToken));

    });

 afterEach(() => {
        sinonSandbox.restore();
    });


    it('Should call success mail once ', async () => {
        mailService.sendSuccessEmail(userEmail, fileModifiedDate);
        chaiAssert.equal(sendMailMock.called, true);
    });

被测代码:


const getMailerClient = async () => {
    const smtpCreds = await getCredentialsFromVault();
    const transporter = nodemailer.createTransport(
        {
            host: "...",
            port: 2525,
            ssl: true,
            auth: {
                user: smtpCreds.user,
                pass: smtpCreds.password
            },
            tls: {
                minVersion: 'TLSv1.2'
            }
        }
    );
    console.log('TRANSPORTER HERE', JSON.stringify(transporter));
// this prints TRANSPORTER HERE  { sendMail: [Function: sendMail] }

    return transporter
}

 
const sendSuccessEmail = async (userEmail, fileModifiedDate) => {
    const transporter = await getMailerClient();
    console.log("HERE IN SUCCESS", JSON.stringify(transporter));
    // this prints HERE IN SUCCCESS { sendMail: [Function: sendMail] }
    await transporter.sendMail(successMailOptions(userEmail, fileModifiedDate));
}

我很确定正在调用模拟,否则我会得到一个错误,但是当我运行测试时,这就是我得到的:

Should call success mail once :
      AssertionError: expected true to equal false
      + expected - actual

      -true
      +false

      at _callee$ (tests\/mailService.test.js:62:20)
      at tryCatch (node_modules\regenerator-runtime\runtime.js:63:40)
      at Generator.invoke [as _invoke] (node_modules\regenerator-runtime\runtime.js:293:22)
      at Generator.next (node_modules\regenerator-runtime\runtime.js:118:21)
      at asyncGeneratorStep (node_modules\@babel\runtime\helpers\asyncToGenerator.js:3:24)
      at _next (node_modules\@babel\runtime\helpers\asyncToGenerator.js:25:9)
      at C:\Users\ekinw\Projects\manage-gp-output-lambda\node_modules\@babel\runtime\helpers\asyncToGenerator.js:32:7
      at new Promise (<anonymous>)
      at Context.<anonymous> (node_modules\@babel\runtime\helpers\asyncToGenerator.js:21:12)
      at processImmediate (internal/timers.js:456:21)

我们将不胜感激任何和所有的帮助!

【问题讨论】:

    标签: node.js unit-testing sinon nodemailer


    【解决方案1】:

    你不需要proxyquire来做,sinon就够了。

    这里是关于如何存根 nodemailer createTransport 以创建虚假 sendMail 函数的示例。

    const sinon = require('sinon');
    const { expect } = require('chai');
    const nodemailer = require('nodemailer');
    const mailService = require('./code.js');
    
    describe('TEST', function () {
      const sandbox = sinon.createSandbox();
      // Create fake sendMail variable to evaluate later.
      const fakeSendMail = sandbox.fake();
      // Create stub nodemailer createTransport which return object with fake sendMail.
      const stubCreateTransport = sandbox.stub(nodemailer, 'createTransport').returns({
        sendMail: fakeSendMail,
      });
    
      it('Should call success mail once ', async function() {
        await mailService.sendSuccessEmail('?', '?');
        expect(stubCreateTransport.called).to.equal(true);
        expect(fakeSendMail.called).to.equal(true);
      });
    });
    

    如果我使用您的代码运行上面的测试代码,它会像这样输出。

    $ npx mocha code.spec.js 
    
    
      TEST
    TRANSPORTER HERE {
      sendMail: [Function: fakeInstance] { displayName: 'fake', id: 'fake#0' }
    }
    HERE IN SUCCESS {
      sendMail: [Function: fakeInstance] { displayName: 'fake', id: 'fake#0' }
    }
        ✓ Should call success mail once 
    
    
      1 passing (5ms)
    

    注意:

    我将console.log('TRANSPORTER HERE', JSON.stringify(transporter)); 更改为console.log('TRANSPORTER HERE', transporter); 进行检查。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-08
      • 2017-01-27
      • 2016-04-21
      • 2018-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-26
      相关资源
      最近更新 更多