Несколько заглушек Sinon против глобального окна не работают должным образом

1

Я использую Karma с Mocha, Chai и Sinon для проверки кода в проекте с использованием этого шаблона. В тесте Subject Test используется API синтеза речи.

Я начинаю с создания window.speechSynthesis.getVoices в методе beforeEach

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

Тогда у меня есть два тестовых примера, в каждом из них я хочу проверить, что происходит, когда возвращается другой набор голосов. Для этого я использую заглушки Sinon

Первый тестовый пример

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 во время второго тестового примера, он получает результаты от первого заглушки. Как будто второй заглушка ничего не делает...

Если я прокомментирую первый тестовый пример, второй тестовый пример будет успешным, но если я оставлю их обоих, второй будет терпеть неудачу, потому что возвращается неправильный набор голосов.

Любая идея, как заставить вторую заглушку работать так, как ожидалось?

  • 0
    Попробуйте создать заглушки только один раз в before тем
  • 0
    @Troopers Как я буду менять данные между тестовыми beforeEach если перенесу заглушку в beforeEach ?
Показать ещё 5 комментариев
Теги:
unit-testing
mocha
sinon
karma-runner

2 ответа

1
Лучший ответ

Ваша заглушка не разрушается между тестами. Вам необходимо восстановить функцию по умолчанию после теста и создать заглушку только один раз before

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'}]));
    });
});
  • 0
    Я добавил afterEach , но результаты те же. Создание заглушки теперь только в beforeEach как у вас здесь.
  • 0
    не перед каждым, но перед
Показать ещё 3 комментария
0

Во-первых, большие до @Troopers. Просто добавив этот ответ, чтобы поделиться окончательным решением и деталями, которые я заметил на этом пути.


Реальный трюк заключался в добавлении переменной уровня тестового уровня, let getVoicesStub, затем определении метода afterEach для restore исходной функции

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

Тонкое замечание к @Troopers предложению об определении окурка в before тем способом -

Если заглушка определена вне тестовых примеров, я должен использовать beforeEach, если в тестовых случаях установлен заглушка, я должен использовать метод before.

В обоих случаях значение afterEach является критическим! Я поселился в решении beforeEach поскольку заглушка определена только в одном месте, поэтому немного меньше кода.

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 ..
    });
});

Ещё вопросы

Сообщество Overcoder
Наверх
Меню