«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Резюме Jest: безопасно имитировать свойства и методы глобальных объектов

Резюме Jest: безопасно имитировать свойства и методы глобальных объектов

Опубликовано 5 августа 2024 г.
Просматривать:241

Jest Recap: Safely Mock Properties and Methods of Global Objects

ТЛ;ДР:

  • Вы хотите избежать влияния переопределенных/издевательских свойств/методов на другие тесты.
  • Для локальных объектов (созданных и принадлежащих этому тесту) вы можете (и должны) использовать
    • localObject.theAnswer = 42 и
    • localObject.calcTheAnswer = jest.fn(() => 42).
  • Для глобальных объектов следует использовать
    • jest.replaceProperty(globalObject, "theAnswer", 42) и
    • jest.spyOn(globalObject, "calcTheAnswer").mockReturnValue(42).
  • Убедитесь, что jest.restoreAllMocks() вызывается в хуке afterEach().

Что?

В идеальном мире кодовой базе нет необходимости манипулировать глобальными объектами, но мир кодовые базы беспорядочен - и поэтому тестируется.

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

Издевательские свойства

Наивный подход к имитации значений — просто установить для свойств любое значение, необходимое вам в тесте.
Это нормально, если вы меняете значения в локальных объектах, принадлежащих (созданных) этим конкретным тестом:

describe("override properties of local objects", () => {
    it("works and is harmless", () => {
        const myArray = [1];
        myArray.length = 0;
        expect(myArray).toHaveLength(0);
    });
    it("does not affect the next test", () => {
        const myArray = [1];
        expect(myArray).toHaveLength(1);
    });
});

Если вы сделаете это для глобальных объектов, получится путаница:

describe("don't override properties of global objects", () => {
    it("works before the property is overridden", () => {
        expect(window.innerWidth).toBeGreaterThan(0);
    });
    it("works, but is evil", () => {
        window.innerWidth = 0;
        expect(window.innerWidth).toBe(0);
    });
    it("fails in the test after the property was overridden", () => {
        expect(() => {
            expect(window.innerWidth).toBeGreaterThan(0); // 



Вот для чего был создан jest.replaceProperty():

describe("use jest.replaceProperty() to override properties of global objects", () => {
    afterEach(() => {
        jest.restoreAllMocks();
    });
    it("works before the property is overridden", () => {
        expect(window.innerWidth).toBeGreaterThan(0);
    });
    it("works and is harmless", () => {
        jest.replaceProperty(window, "innerWidth", 0);
        expect(window.innerWidth).toBe(0);
    });
    it("does not affect the next test", () => {
        expect(window.innerWidth).toBeGreaterThan(0);
    });
});

Методы издевательств

Методы можно имитировать аналогично свойствам.

describe("override methods of local objects using jest.fn()", () => {
    it("works and is harmless", () => {
        const mySet = new Set([1]);
        mySet.has = jest.fn().mockReturnValue(false);
        expect(mySet.has(1)).toBeFalsy();
    });
    it("does not affect the next test", () => {
        const mySet = new Set([1]);
        expect(mySet.has(1)).toBeTruthy();
    });
});

Если вы используете myObject.someFunction = jest.fn() для глобальных объектов, ваши тесты могут зависеть друг от друга и потерять свой смысл:

describe("don't override methods of global objects using jest.fn()", () => {
    it("works before the method is overridden", () => {
        expect(document.getElementById("foo")).toBeNull();
    });
    it("works, but is evil", () => {
        const el = document.createElement("div");
        document.getElementById = jest.fn().mockReturnValue(el);

        expect(document.getElementById("foo")).toBe(el);
    });
    it("fails in the test after the property was overridden", () => {
        expect(() => {
            expect(document.getElementById("foo")).toBeNull(); // 



Как нам следует имитировать методы в глобальных объектах? Вот для чего хорош jest.spyOn():

describe("use jest.spyOn() to override methods of global objects", () => {
    afterEach(() => {
        jest.restoreAllMocks();
    });
    it("works before the method is overridden", () => {
        expect(document.getElementById("foo")).toBeNull();
    });
    it("works and is harmless", () => {
        const el = document.createElement("div");
        jest.spyOn(document, "getElementById").mockReturnValue(el);

        expect(document.getElementById("foo")).toBe(el);
    });
    it("does not affect the next test", () => {
        expect(document.getElementById("foo")).toBeNull();
    });
});

Вы должны очиститься

Если вы хотите быть уверены, что все тесты находят систему в одном и том же (свежем, чистом) состоянии, вам необходимо восстанавливать состояние макетов после каждого теста.

Самое простое решение — установить свойство конфигурации restreMocks.

Самый простой вариант — вызвать jest.restoreAllMocks() в afterEach()

Как что-то имитировать для всех тестов

Иногда вам нужно замокать все тесты в файле. Если вы используете jest.spyOn() и jest.replaceProperty() на верхнем уровне или в блоке описания(), все Mocks будут сброшены после выполнения первого теста.

На верхнем уровне вы можете безопасно переопределять свойства и методы без jest.spyOn() и jest.replaceProperty().

Если вы хотите создавать макеты только для блока описания(), вам нужно выполнить эти вызовы в хуке beforeEach().

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/htho/jest-recap-safely-mock-properties-and-methods-of-global-objects-3ph8?1. Если есть какие-либо нарушения, свяжитесь с Study_golang@163. .com, чтобы удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3