Модульное тестирование класса ES6 с внешней зависимостью

Я пытаюсь установить шаблон модульного тестирования для своей компании. Наши клиентские проекты построены с использованием классов ES6 и зависят от нашего основного продукта. Код внешнего интерфейса оборачивается в процессе сборки целым другим блоком кода, который, по сути, является замыканием и фиксирует зависимость. Поэтому нам не нужно вручную импортировать его, чтобы использовать.

Допустим, зависимость называется productScope, и это объект, который имеет некоторые модели DOM, внутренние API-интерфейсы и параметры, среди прочего, необходимые для каждого проекта. На данный момент Мокко кидает ReferenceError: productScope is not defined. Как можно поиздеваться над этим объектом? Или я должен просто использовать реальный объект?

Пример:

class someClass {
    constructor() {
        const id = productScope.items[0].id
        const item = productScope.domModel.querySelector('.some-div')

        item.classList.add(`added-${id}`)
    }
}

Это завернуто в основной код, как показано ниже:

(function(productScope) {
    // front end code goes here
}(productScope)

Файл тестирования:

import someClass from '../../js/someClass'

describe('someClass', function() {
    const someClass = new someClass()
    it('should be a class', function() {
        console.info(someClass)
    });
});

Измените свой вопрос, включив в него соответствующие части кода модульного теста.

Patrick Hund 20.11.2018 18:18

Вот ответ в стиле вашего вопроса: Прочтите это: gofreerange.com/mocha/docs/Mocha/Mock.html

Randy Casburn 20.11.2018 18:25

@PatrickHund добавил код

Jaeeun Lee 20.11.2018 18:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
3
1 040
3

Ответы 3

Похоже, productScope - это глобальная переменная.

Что-то вроде этого должно сработать для вас.

import someClass from '../../js/someClass';

describe('someClass', function() {
    let someClass;

    beforeEach(() => {
        global.productScope = {
          // you mock definition
          someClass = new someClass();
        };
    });

    it('should be a class', function() {
        console.info(someClass)
    });
});

Спасибо, но все та же ошибка, плюс сообщение 1) "before each" hook for "should be a class" красным цветом.

Jaeeun Lee 21.11.2018 02:02

Откуда вы берете productScope? Вы импортируете его в свой файл или это глобальная переменная?

Dinesh Pandiyan 21.11.2018 02:04

По сути, есть целый блок кода, который обертывает внешний код, и это закрытие, которое захватывает productScope.

Jaeeun Lee 21.11.2018 02:06

Если это закрытие, вы можете заглушить его с помощью sinon. Можете показать, как импортировать productScope в файл js/someClass?

Dinesh Pandiyan 21.11.2018 02:52

Мне не нужно импортировать его в класс, потому что класс как бы обернут в него. Может быть, как если бы вы использовали $ as jQuery внутри IIFE.

Jaeeun Lee 21.11.2018 06:33

Похоже, у вас сложная настройка кода. Можете ли вы добавить весь код для ясности?

Dinesh Pandiyan 21.11.2018 07:10

Вы можете попробовать что-то вроде этого

describe('#someClass', () => {
    let someClass;

    beforeEach(() => {
        global.productScope = {
            // mocking productScope object
        };
    });

    it('should be a class', () => {
        someClass = new SomeClass;
        console.info(someClass);
    });

    afterEach(() => {
        delete global.productScope;
    });
});

или, в качестве альтернативы, если вам нужна более конкретная фиктивная логика для каждого тестового примера

describe('#someClass', () => {
    let someClass;

    it('should be a class', () => {
        global.productScope = {
            // mocking productScope object
        };

        // Test logic start

        someClass = new SomeClass;
        console.info(someClass);

        // Test logic end

        delete global.productScope;
    });
});

У меня есть и другие ответы, так как управление переменными global кажется самым простым и понятным решением.

Однако вы можете использовать нанизывать для получения строкового представления класса и оценка для привязки к области закрытия:

class someClass {
   constructor() {
     this.id = scopedId
   }
}

// pass class as an argument
function scopeFactory(classDef) {

   // define scoped data
   let scopedId = 2;

   // eval is used to bind class to the local closure
   // so `scopedId` will be in charge
   return eval("(" + classDef + ")");
}

const scopedSomeClass = scopeFactory(someClass);

console.info(new scopedSomeClass)

Обратите внимание, что eval(someCLass.toString())не работает без скобок.

Вы можете добавить его в свой проект как вспомогательную функцию.

Другие вопросы по теме