Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/414.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 针对全局窗口的多个Sinon存根未按预期工作_Javascript_Unit Testing_Mocha.js_Karma Runner_Sinon - Fatal编程技术网

Javascript 针对全局窗口的多个Sinon存根未按预期工作

Javascript 针对全局窗口的多个Sinon存根未按预期工作,javascript,unit-testing,mocha.js,karma-runner,sinon,Javascript,Unit Testing,Mocha.js,Karma Runner,Sinon,我正在与Mocha、Chai和Sinon一起使用Karma测试一个项目中的代码。被测对象使用API 我首先在一个beforeach方法中建立window.speechSynthesis.getVoices beforeEach(() => { global.window.speechSynthesis = { getVoices: () => (null), }; }); 然后我有两个测试用例,在每一个测试用例中,我想测试当返回一组不同的声音时会发生

我正在与Mocha、Chai和Sinon一起使用Karma测试一个项目中的代码。被测对象使用API

我首先在一个
beforeach
方法中建立
window.speechSynthesis.getVoices

beforeEach(() => {
    global.window.speechSynthesis = {
        getVoices: () => (null),
    };
});
然后我有两个测试用例,在每一个测试用例中,我想测试当返回一组不同的声音时会发生什么。为了实现这一点,我正在使用

第一个测试用例

it('supports speech and locale', () => {
    const getVoicesStub = sinon.stub(
        global.window.speechSynthesis,
        'getVoices');

    getVoicesStub.callsFake(() => (
        [{lang: 'en_US'}]
    ));
it('will choose best matching locale', () => {
    const getVoicesStub = sinon.stub(
        global.window.speechSynthesis,
        'getVoices');

    getVoicesStub.callsFake(() => (
        [{lang: 'es_MX'}, {lang: 'es_US'}]
    ));
第二个测试用例

it('supports speech and locale', () => {
    const getVoicesStub = sinon.stub(
        global.window.speechSynthesis,
        'getVoices');

    getVoicesStub.callsFake(() => (
        [{lang: 'en_US'}]
    ));
it('will choose best matching locale', () => {
    const getVoicesStub = sinon.stub(
        global.window.speechSynthesis,
        'getVoices');

    getVoicesStub.callsFake(() => (
        [{lang: 'es_MX'}, {lang: 'es_US'}]
    ));
问题是,当SUT在第二个测试用例中调用
window.speechSynthesis.getVoices
时,它从第一个存根中获取结果。好像第二个存根什么都没做

如果我注释掉第一个测试用例,第二个测试用例成功,但是如果我将它们都保留在注释中,第二个测试用例失败,因为返回了错误的语音集


知道如何让第二个存根按预期工作吗?

在测试之间不会销毁存根。您需要在测试之后恢复默认函数,并在测试之前的
中只创建一次存根

describe("Test suite", () => {

    let getVoicesStub;

    before(() => {
        // executes before suite starts
        global.window.speechSynthesis = {
            getVoices: () => (null),
        };

        getVoicesStub = sinon.stub(global.window.speechSynthesis, 'getVoices');
    });

    afterEach(() => {
        // executes after each test
        getVoicesStub.restore();
    });

    it('supports speech and locale', () => {
        getVoicesStub.callsFake(() => ([{lang: 'en_US'}]));
    });

    it('will choose best matching locale', () => {
        getVoicesStub.callsFake(() => ([{lang: 'es_MX'}, {lang: 'es_US'}]));
    });
});

首先,向@Troopers致敬。只是添加这个答案来分享最终的解决方案和我在过程中注意到的细节


真正的诀窍是添加一个测试套件级别的变量
let getVoicesStub
,然后在每个
方法之后定义一个
,以
还原原始函数

afterEach(() => {
    getVoicesStub.restore();
});
关于在
方法之前定义
存根的@Troopers建议-

如果存根是在测试用例之外定义的,我必须在每个
之前使用
,如果存根是在测试用例中定义的,我必须在
之前使用
方法

在这两种情况下,每次
之后的
都是至关重要的!我在每个
解决方案之前都选择了
,因为存根只在一个地方定义,所以代码稍微少一些

describe('Browser Speech', () => {
    let getVoicesStub;

    beforeEach(() => {
        global.window.speechSynthesis = {
            getVoices: () => (null),
        };

        getVoicesStub = sinon.stub(
            global.window.speechSynthesis,
            'getVoices');
    });

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

    it('supports speech and locale', () => {
        getVoicesStub.callsFake(() => (
            [{lang: 'en_US'}]
        ));

        // test case code ..
    });

    it('will choose best matching locale', () => {
        getVoicesStub.callsFake(() => (
            [{lang: 'es_MX'}, {lang: 'es_US'}]
        ));


        // test case code ..
    });
});

之前,尝试在
中只创建一次存根
@Troopers如果我在每个
之前将存根移动到
中,我将如何更改测试用例之间的数据?您的存根在两个测试之间是相同的,您只能在每个测试中更改callsFake如何在没有全局属性的情况下执行此操作?我需要一些方法来引用测试用例中的存根,但是当我定义一个全局属性时,我得到了这个错误
严格模式禁止隐式创建全局属性“getVoicesStub”
在测试套件的本地声明存根,而不是在globalI中,在每个
之后添加
,但是结果是相同的。存根创建现在只在每个
之前进行。尝试过,结果相同。因此,在第二个测试用例中,在调用
getVoicesStub.callsFake()
之后,它仍然返回
null
。我还尝试了
global.window.speechSynthesis.getVoices.restore()
,得到了相同的结果。不过,我同意你的看法,你的解决方案看起来应该有效。我会继续试验的,让它发挥作用!!将把细节放在一个单独的答案中,这样就可以了。