How to access and test an internal (non-exports) function in a node.js module?

后端 未结 8 1961
别跟我提以往
别跟我提以往 2020-12-12 09:31

I\'m trying to figure out on how to test internal (i.e. not exported) functions in nodejs (preferably with mocha or jasmine). And i have no idea!

Let say I have a mo

8条回答
  •  一整个雨季
    2020-12-12 10:12

    Working with Jasmine, I tried to go deeper with the solution proposed by Anthony Mayfield, based on rewire.

    I implemented the following function (Caution: not yet thoroughly tested, just shared as a possibile strategy):

    function spyOnRewired() {
        const SPY_OBJECT = "rewired"; // choose preferred name for holder object
        var wiredModule = arguments[0];
        var mockField = arguments[1];
    
        wiredModule[SPY_OBJECT] = wiredModule[SPY_OBJECT] || {};
        if (wiredModule[SPY_OBJECT][mockField]) // if it was already spied on...
            // ...reset to the value reverted by jasmine
            wiredModule.__set__(mockField, wiredModule[SPY_OBJECT][mockField]);
        else
            wiredModule[SPY_OBJECT][mockField] = wiredModule.__get__(mockField);
    
        if (arguments.length == 2) { // top level function
            var returnedSpy = spyOn(wiredModule[SPY_OBJECT], mockField);
            wiredModule.__set__(mockField, wiredModule[SPY_OBJECT][mockField]);
            return returnedSpy;
        } else if (arguments.length == 3) { // method
            var wiredMethod = arguments[2];
    
            return spyOn(wiredModule[SPY_OBJECT][mockField], wiredMethod);
        }
    }
    

    With a function like this you could spy on both methods of non-exported objects and non-exported top level functions, as follows:

    var dbLoader = require("rewire")("../lib/db-loader");
    // Example: rewired module dbLoader
    // It has non-exported, top level object 'fs' and function 'message'
    
    spyOnRewired(dbLoader, "fs", "readFileSync").and.returnValue(FULL_POST_TEXT); // method
    spyOnRewired(dbLoader, "message"); // top level function
    

    Then you can set expectations like these:

    expect(dbLoader.rewired.fs.readFileSync).toHaveBeenCalled();
    expect(dbLoader.rewired.message).toHaveBeenCalledWith(POST_DESCRIPTION);
    

提交回复
热议问题