简体   繁体   中英

Testing TypeScript function which is not exported

I use Mocha/Chai for testing JavaScript front-end code and now we switched to TypeScript. I have several functions I want to test. But they shouldn't be exportable. Can I get an access to this functions and test it without adding export to them?

There is no way to access a non-exported module function.

module MyModule {
    function privateFunction() {
        alert("privateFunction");
    }
}
MyModule.privateFunction(); // Generates a compiler error

However, leaving aside the question of validity of private method testing, here is what you can do.

Group your functions into an utility class, and then leverage the fact that private class members can be accessed via square bracket notation.

module MyModule {
    export class UtilityClass {
        private privateFunction() {
            alert("privateFunction");
        }   
    }
}
var utility = new MyModule.UtilityClass();
//utility.privateFunction(); Generates a compiler error
utility["privateFunction"](); // Alerts "privateFunction"

While it is not possible to access non-exported function directly there is still a way to export them in a "semi-hidden" way. One possible approach would be:

// In your library module declare internal functions as non-exported like normal.
function someInternalFunctionA(x: number): number {
  return x;
}

function someInternalFunctionB(x: number): number {
  return x;
}

// At the bottom, offer a public escape hatch for accessing certain functions
// you would like to be available for testing.
export const _private = {
  someInternalFunctionA,
  someInternalFunctionB,
};

On test side you can do:

import { _private } from "./myModule";

test("someInternalFunctionA", () => {
  expect(_private.someInternalFunctionA(42)).toEqual(42);
});

What I like about the approach:

  • No need to mark someInternalFunctionA with export directly.
  • It should still be very obvious that the stuff under _private isn't officially part of the public interface.

As you can see in related questions the issue of testing private functions inside classes or modules is heavily debated on StackOverflow - The following might be an architectural solution to not even have that discussion:

If these functions feel important enough to be tested separately, but should not be accessible as part of a module, should they maybe be placed in their own module?

This would solve your issue of accessibility - they now are public functions in one module, and you can easily use them from within another module and not expose them as part of that module.

Best solution I found is to export the private function under different name so this name will remind you not to use this function anywhere else.

export const getPriceTEST = getPrice;

function getPrice(): number {
  return 10 + Math.Random() * 50;
}

But they shouldn't be exportable. Can I get an access to this functions and test it without adding export to them?

In general, no. It's possible to access private class members, but not unexported members of modules.

I would echo @Katana314's comments -- unit tests should not be concerning themselves with non-public methods. Trying to do so is an indication that you're testing the implementation details of the module rather than the contract the module claims to implement.

This is a total hack, but hey...

window.testing = {};

Then in your module:

module.exports = {
    myPublicFunction: myPublicFunction
};

window.testing.myModule = {
    myPublicFunction: myPublicFunction,
    myPrivateFunction: myPrivateFunction
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM