无法使用Sinon存根函数

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

我有一个Redux动作,它本身会调度另外两个动作。从导入的函数中检索每个操作。一个来自本地模块,另一个来自外部库。

import { functionA } from './moduleA';
import { functionB } from 'libraryB';

export function myAction() {
  return (dispatch) => {
    dispatch(functionA());
    ...
    dispatch(functionB());
  }
}

在我的测试中,我使用sinon沙箱来删除函数,但只有两个测试通过。我期待所有3通过。

import * as A from './moduleA';
import * as B from 'libraryB';

describe(__filename, async () => {
  it('Calls 2 other actions', () => {
    sandbox = sinon.sandbox.create();

    const dispatch = sandbox.stub();

    sandbox.stub(A, 'functionA');
    sandbox.stub(B, 'functionB');

    await myAction()(dispatch);

    // passes
    expect(dispatch.callCount).to.equal(2);

    //passes
    expect(A.functionA).to.have.been.called();

    // fails
    expect(B.functionB).to.have.been.called();     
  });
});

最后一个期望失败并出现错误:

TypeError:[功能:功能]不是间谍或对间谍的调用!

当我将函数输出到控制台时,我得到了这个,这似乎与Babel导入导出导出(ES6 re-exported values are wrapped into Getter)的方式有关。这些功能可以正常工作,而不是在测试中。

{ functionA: [Function: functionA] }
{ functionB: [Getter] }

我尝试过使用stub.get(getterFn),但这只是给了我错误:

TypeError:无法重新定义属性:fetchTopicAnnotations

javascript redux sinon
2个回答
0
投票

你试过命名你的存根吗?你的代码读起来有点奇怪。在测试的任何时候,你都没有提到你的存根。

import * as A from './moduleA';
import * as B from 'libraryB';

describe(__filename, async () => {
  it('Calls 2 other actions', () => {
    sandbox = sinon.sandbox.create();

    const dispatch = sandbox.stub();

    const functionAStub = sandbox.stub(A, 'functionA');
    const functionBStub = sandbox.stub(B, 'functionB');

    await myAction()(dispatch);

    // passes
    expect(dispatch.callCount).to.equal(2);

    //passes
    expect(functionAStub.called).toBe(true);

    // fails
    expect(functionBStub.called).toBe(true);     
  });
});

0
投票

很难说100%,但似乎模块正在导入,因此在测试存根之前直接引用该函数。 Sinon将有效地替换export对象上的函数,但是另一个模块将首先导入并获得对实际函数的引用,替换它不会导致它重新加载。

你可以试验它并通过改变你的模块来证明这一点:

import * as A from './moduleA';
import * as B from 'libraryB';

export function myAction() {
  return (dispatch) => {
    dispatch(A.functionA());
    ...
    dispatch(B.functionB());
  }
}

这将基本上在调用时查找对函数A /函数的引用,这将允许使用存根替换它们。

如果你发现它很糟糕并希望保留原始表单,那么我相信你需要使用第二个名为proxyquire的库,这将有效地让你存根导入的整个模块。

您的测试函数最终会看起来更像这样:

import * as proxyquire from 'proxyquire'
// import * as A from './moduleA'
// import * as B from 'libraryB'

describe(__filename, async () => {
  const A = {}
  const B = {}
  const functionAStub = sandbox.stub(A, 'functionA')
  const functionBStub = sandbox.stub(B, 'functionB')
  const { myAction } = proxyquire('./myAction', {
    './moduleA': A,
    'libraryB': B
  })
  ...
})

在您需要使用模块而不是真实模块的情况下调用代理查询时,才会导入被测模块。

然后,您可以按预期在测试中引用这些存根。

© www.soinside.com 2019 - 2024. All rights reserved.