5

I'm trying to set a unit testing boilerplate for my company. Our front end projects are built with ES6 classes and have a dependency to our core product. The front end code gets wrapped through a build process in a whole other block of code that is basically a closure and captures the dependency. So we don't have to manually import it in order to use it.

Let's say the dependency is called productScope and it's an object that has some DOM models, internal APIs and parameters among many other things necessary for each project. At the moment, Mocha throws ReferenceError: productScope is not defined. How can I mock this object? Or should I just use the actual object?

Example:

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

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

This get wrapped in core code like below:

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

Testing file:

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

describe('someClass', function() {
    const someClass = new someClass()
    it('should be a class', function() {
        console.log(someClass)
    });
});
3
  • Please edit your question to include relevant parts of your unit test code Commented Nov 20, 2018 at 17:18
  • Here is an answer that is in the style of your question: Read this: gofreerange.com/mocha/docs/Mocha/Mock.html Commented Nov 20, 2018 at 17:25
  • @PatrickHund added some code Commented Nov 20, 2018 at 17:39

3 Answers 3

1

You can try something like this

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

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

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

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

or alternatively if you want more specific mock logic for each test case

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

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

        // Test logic start

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

        // Test logic end

        delete global.productScope;
    });
});
Sign up to request clarification or add additional context in comments.

Comments

0

Looks like productScope is a global variable.

Something like this should work for you.

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

6 Comments

Thanks, but still the same error, plus 1) "before each" hook for "should be a class" message in red.
Where are you getting productScope from? Are you importing it in your file or is it a global variable?
Basically, there is a whole block of code that wraps the front end code, and it's a closure that captures productScope
If it's a closure, you could stub it with sinon. Can you show how you import productScope in the js/someClass file?
I don’t need to import it to the class because the class is kind of wrapped in it. Perhaps like how you’d use the $ as jQuery inside of an IIFE.
|
0

I'm with other answers as well, as managing global variables seems to be the simplest and most straightforward solution.

However, you can use toString to get class's string representation, and eval it to bind to closure's scope:

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.log(new scopedSomeClass)

Note that eval(someCLass.toString()) doesn't work without parentheses.

You can add it as a helper function, into your project.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.