Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest fail to spy in object

We had a disturbing error while using Jest for our unit test.

The problem: Jest do not access to the inner object method

The case: there's a lol object with a and b() method, if we call the b method directly, Jest fail, if we call it with lol.b() it works

Did someone already have encountered this problem? Is there a better workaround?

The code:

describe('Jest bug', () => {    
    it('Jest fail', () => {
        const lol = (() => {
            const a = () => {
                console.log("console a");
                b();
            };
            const b = () => {
                console.log("console b");
            };
            return {
                a,
                b
            };
        })();

        const spy = jest.spyOn(lol, 'b');

        lol.a();

        expect(spy).toHaveBeenCalled()
    });

    it('Jest success', () => {
        const lol = (() => {
            const a = () => {
                console.log("console OK a");
                lol.b();
            };
            const b = () => {
                console.log("console OK b");
            };
            return {
                a,
                b
            };
        })();

        const spy = jest.spyOn(lol, 'b');

        lol.a();

        expect(spy).toHaveBeenCalled()
    });

});
like image 902
romuleald Avatar asked Jan 23 '26 08:01

romuleald


1 Answers

Jest spyOn internally replaces object method whith spy function - the spy function is 'attached' to object, it doesn't wrap original function to which object property points. If you set spy on lol.b method Jest does something like this (of course below code is huge simplification and is just to show general idea):

let b = function() {
  ...
}; 

let lol = {
    b: b
};

spyOn(lol, 'b');
//Jest internally does something like this
lol.b = function jestSpyFunction() {
   ...
};

So if you now call b() directly Jest spy is totally not aware of this because jestSpyFunction is not called in such case - it will be called only if you use lol.b().
So in my opintion your second implementaion of lol is correct and it should be done this way to make code testable. Besides, you define a and b functions as 'private' (inside anonymous function) so it's correct and intended behaviour that they're not accessible from the outer scope (even by Jest spies).

like image 56
Bartek Fryzowicz Avatar answered Jan 25 '26 20:01

Bartek Fryzowicz