【问题标题】:Sinon Spy never called but it should beSinon Spy 从未打过电话,但应该打
【发布时间】:2019-07-07 15:08:20
【问题描述】:

问题

我正在使用 Jest 和 SinonJS 测试自定义 redux 中间件,更准确地说,我想测试是否在中间件内部的特殊条件下调用某些函数。

我使用 SinonJS 创建间谍,并使用 Jest 运行测试。我为要跟踪的特定功能初始化了间谍,当我检查是否调用了间谍时,即使应该(手动测试),间谍也没有被调用。

代码

这是我要测试的中间件:

import { Cookies } from 'react-cookie';
import setAuthorizationToken from './setAuthorizationToken';

let cookies = new Cookies();

export const bindTokenWithApp = (store) => (next) => (action) => {
    // Select the token before action
    const previousToken = getToken(store.getState());
    // Dispatch action
    const result = next(action);
    // Select the token after dispatched action
    const nextToken = getToken(store.getState());

    if (previousToken !== nextToken) {
        if (nextToken === '') {
            setAuthorizationToken(false);
            cookies.remove(SESSION_COOKIE_NAME, COOKIE_OPTIONS);
        } else {
            cookies.set(SESSION_COOKIE_NAME, nextToken, COOKIE_OPTIONS);
            setAuthorizationToken(nextToken);
        }
    }

    return result;
};

这是我的实际测试

import { bindTokenWithApp } from './middleware';
import { Cookies } from 'react-cookie';
import sinon, { assert } from 'sinon';
import setAuthorizationToken from './setAuthorizationToken';

describe('bindTokenWithApp', () => {
    const next = jest.fn();
    const action = jest.fn();
    let cookies = new Cookies();

    it('removes cookies when there is no token', () => {
        // My actual not working spies
        const cookieSpy = sinon.spy(cookies.remove);
        const authSpy = sinon.spy(setAuthorizationToken);

        // Stub for the specific case. This code works, 
        // I console.logged in the middleware and I'm getting the below values
        const getState = sinon.stub();
        getState.onFirstCall().returns({ auth: { token: 'a token' } });
        getState.onSecondCall().returns({ auth: { token: '' } });
        const store = { getState: getState };

        bindTokenWithApp(store)(next)(action);

        assert.calledOnce(cookieSpy);
        assert.calledOnce(authSpy);
        // Output : AssertError: expected remove to be called once but was called 0 times
        // AssertError: expected setAuthorizationToken to be called once but was called 0 times

        cookieSpy.restore(); // <= This one works
        authSpy.restore(); // TypeError: authSpy.restore is not a function 

  });
});

我已经阅读了 SinonJS 文档和一些 StackOverFlow 帖子,但没有解决方案。我也不能打电话给authSpy.restore();。我认为我没有以正确的方式初始化间谍,我误解了 SinonJS 中的一个概念,但我找不到哪个!

setAuthorizationToken 签名是
(别名) const setAuthorizationToken: (token: any) => void
导入 setAuthorizationToken

我认为这是一个经典模块,所以我不明白为什么我与authSpy.restore(); 斗争

【问题讨论】:

    标签: javascript unit-testing sinon spy


    【解决方案1】:

    您拥有的两个间谍实际上有两个不同的修复程序,都具有相同的潜在问题。 sinon.spy(someFunction) 实际上并没有包装 someFunction 本身,它为它返回一个间谍但不执行任何替换。

    对于第一个间谍,存在一个自动包装对象方法的简写:sinon.spy(cookie, 'remove') 应该做你需要的。

    对于第二个间谍,它更复杂,因为您需要将间谍包裹在setAuthorizationToken 的默认导出周围。为此,您将需要诸如 proxyquire 之类的东西。 Proxyquire 是一种专门的 require 机制,允许您用所需的测试方法替换导入。以下是您需要做的简要说明:

    const authSpy = sinon.spy(setAuthorizationToken);
    bindTokenWithApp = proxyquire('./middleware', { './setAuthorizationToken': authSpy});
    

    【讨论】:

    • 感谢您的解释。我已经尝试了这两种解决方案,但都没有奏效。我了解潜在的问题,对于我现在在测试中拥有的第一个间谍:sinon.spy(cookies, 'remove'); assert.calledOnce(cookies.remove); 但具有相同的输出。对于第二个间谍,我尝试了 proxyquire 和 jest.mock (来自 article 但没有成功)。我不能断言 bindTokenWithApp = proxyquire… 因为它是只读的导入。当我断言const bindTokenWithApp =… 时,我无法执行它,因为它不是一个函数……
    猜你喜欢
    • 1970-01-01
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多