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?

- 1,729
- 7
- 27
- 53
-
7I think this is a general programming observation; unit tests should not focus on private methods. If you have private methods that are not covered by certain usage of public methods, then just get rid of them. If they are covered by use of public methods, use those public methods. (Simplistic viewpoint, but that's the idea) – Katana314 Aug 10 '15 at 15:06
-
How do you deal with these problems before switching to TypeScript? – Artem Aug 13 '15 at 17:31
-
@Katana314 I want to do some benchmark on a non-exported function. How can I do that? This isn't about the test philosophy. – Amin Ya Apr 04 '20 at 08:51
-
1@Katana314 From what I can tell this view is a bit out-of-vogue. There are perfectly valid use cases for testing internal methods. Over the years I've encountered many examples of private functions that even allowed for more meaningful **unit** testing compared to their higher level public interface. The ideal granularity of unit testing simply doesn't always have to coincide with the ideal public interface. Also note that modern languages (e.g. Rust) often go for a design that even encourages private testing. – bluenote10 Dec 23 '20 at 09:57
-
Also see [related question regarding private methods](https://stackoverflow.com/questions/35987055/how-to-write-unit-testing-for-angular-typescript-for-private-methods-with-jasm). – bluenote10 Jan 08 '21 at 22:27
-
Does this answer your question? [How can I unit test non-exported functions?](https://stackoverflow.com/questions/54116070/how-can-i-unit-test-non-exported-functions). Typescript is Javascript++, so this is really a duplicate of that question. – Inigo May 03 '22 at 21:19
6 Answers
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"

- 5,958
- 2
- 21
- 28
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
withexport
directly. - It should still be very obvious that the stuff under
_private
isn't officially part of the public interface.

- 23,414
- 14
- 122
- 178
-
If you are doing TDD correctly, there should be no code running in production whose purpose is just for testing. Besides being misleading, it might be a potential source of problems. – Teodoro Oct 07 '21 at 23:46
-
2@Teodoro Of course, this isn't a great solution, but from a pragmatic perspective: (1) the code exporting the private symbols is a very minor form "running code for testing in production", (2) this has never caused trouble in the projects I've worked on in real life, (3) the possibility to test more fine-grained internal function definitely has helped us in delivering correct code. – bluenote10 Oct 08 '21 at 07:47
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.

- 10,607
- 1
- 36
- 64
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 getPrice__test = getPrice;
function getPrice(): number {
return 10 + Math.Random() * 50;
}

- 3,937
- 2
- 25
- 35
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.

- 209,514
- 56
- 272
- 235
-
So, I must export function if I want to test it or replace it by a stub. Am I right? – michaeluskov Aug 13 '15 at 09:56
-
The contention being made is that you should not export something solely for the sake of testing. You are unit testing the module to make sure that passing in a set of values gives you the expected results, not the internal processing flow within the module. – Brocco Aug 13 '15 at 15:24
This is a total hack, but hey...
window.testing = {};
Then in your module:
module.exports = {
myPublicFunction: myPublicFunction
};
window.testing.myModule = {
myPublicFunction: myPublicFunction,
myPrivateFunction: myPrivateFunction
};

- 8,339
- 7
- 36
- 53