如何使用 sinon.js 模拟导出函数?

问题描述 投票:0回答:2

所以我有一个名为

article.js
的文件,如下所示:

import a from 'indefinite';

function formatArticle(value) {
  return a(value);
}

export { formatArticle };
export default formatArticle;

还有一个名为

index.js
的文件,如下所示:

import formatArticle from './article';

const format = (value, incomingFormat) => {
  if (incomingFormat === 'indefinite') {
    return formatArticle(value);
  }

  return value;
};

export default format;

我正在尝试测试我正在导入的 formatArticle 函数是否在应该调用的时候被调用。我为此使用

sinon
chai
。这是测试文件:

import chai, { expect } from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';

import format from './index';
import * as article from './article';

chai.use(sinonChai);

describe('format', () => {
    describe('article', () => {
        describe(`when incoming format is 'indefinite'`, () => {
            const value = 'some value';
            const indefinite = 'indefinite';

            let formatArticleSpy;

            beforeEach(() => {
                formatArticleSpy = sinon.spy(article, 'formatArticle');
                format(value, indefinite);
            });

            it('should call formatArticle', () => {
                expect(formatArticleSpy).to.have.been.calledWith(value);
            });
        });
    });
});

但是,每当我运行测试套件时,它都会告诉我:

AssertionError: expected formatArticle to have been called with arguments some value

我在这个设置中做错了什么?使用间谍是尝试执行此操作的正确方法吗?我也尝试过使用 sinon.stub ,得到了相同的结果。

任何帮助表示赞赏!

javascript unit-testing chai sinon sinon-chai
2个回答
1
投票

sinon.js 使用 Link Seams 来存根独立函数。适合您情况的

formatArticle
功能。

例如

article.js

import a from './indefinite';

function formatArticle(value) {
  return a(value);
}

export default formatArticle;

indefinite.js

export default function a(value) {
  return 'real data';
}

index.js

import formatArticle from './article';

const format = (value, incomingFormat) => {
  if (incomingFormat === 'indefinite') {
    return formatArticle(value);
  }

  return value;
};

export default format;

index.test.js

import proxyquire from 'proxyquire';
import sinon from 'sinon';

describe('61104001', () => {
  it('should pass', () => {
    const value = 'some value';
    const indefinite = 'indefinite';
    const formatArticleStub = sinon.stub().returns('fake data');
    const format = proxyquire('./', {
      './article': { default: formatArticleStub },
    }).default;
    const actual = format(value, indefinite);
    sinon.assert.match(actual, 'fake data');
    sinon.assert.calledWithExactly(formatArticleStub, value);
  });
  // you can do the rest
});

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

  61104001
    ✓ should pass (2259ms)


  1 passing (2s)

---------------|---------|----------|---------|---------|-------------------
File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------|---------|----------|---------|---------|-------------------
All files      |   72.73 |       50 |   33.33 |   72.73 |                   
 article.ts    |   66.67 |      100 |       0 |   66.67 | 4                 
 indefinite.ts |      50 |      100 |       0 |      50 | 2                 
 index.ts      |   83.33 |       50 |     100 |   83.33 | 8                 
---------------|---------|----------|---------|---------|-------------------

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


0
投票

仅适用于类或导出的对象,如下所示:

服务.js

const service = {
    a() {
        console.log('a()')
    },

    b() {
        console.log('a()')
        this.a()
    }
}

module.exports = service

测试.js

const service = require(`/service.js`)

const {
    a, b
} = service

describe('[Task ID]', () => {
     let aSpy

     beforeEach(async () => {
         aSpy = sinon.spy(service, 'a')
     })

     it.only('should call a()', async () => {
         await service.b()
         expect(aSpy.called).to.be.equal(true)
     })
 })
  • 我们必须使用service.b()
© www.soinside.com 2019 - 2024. All rights reserved.