Jest: How to Test Private Methods (Best Practices + Examples)
When writing unit tests with Jest, one common challenge developers face is how to test private methods. JavaScript (and especially TypeScript with ES6+ classes) doesn't have "true" private methods like some other languages, but with newer syntax like #privateMethod
, it's becoming more common.
In this guide, you'll learn the different ways to test private methods in Jest, and when it’s best not to.
🔍 What Are Private Methods?
Private methods are internal functions of a class that are not meant to be accessed from the outside. They help with encapsulation and clean architecture.
JavaScript Private Method Syntax (ES2022+)
class MyClass {
#privateMethod() {
return 'secret';
}
publicMethod() {
return this.#privateMethod();
}
}
🧪 Should You Test Private Methods?
Before diving into the how, ask yourself: Do you really need to?
✅ Best practice: Test private methods indirectly by testing public methods that use them.
However, if the private logic is complex and not exposed, testing directly may be justified.
🛠️ How to Test Private Methods in Jest
1. ✅ Test Through Public Methods (Recommended)
If your private method is used in a public method, test that instead.
class Calculator {
#square(n) {
return n * n;
}
getSquarePlusOne(n) {
return this.#square(n) + 1;
}
}
Test:
test('getSquarePlusOne returns correct value', () => {
const calc = new Calculator();
expect(calc.getSquarePlusOne(3)).toBe(10);
});
2. ⚠️ Use Bracket Notation or TypeScript Casting (Non-Private Syntax)
If you're not using the #
syntax, and your method is just conventionally private (e.g. _helper()
), you can still call it in tests.
class MyClass {
_hiddenLogic(val) {
return val + 1;
}
}
Test:
test('calls _hiddenLogic directly', () => {
const instance = new MyClass();
expect(instance._hiddenLogic(2)).toBe(3);
});
This is not truly private, but is commonly used in many codebases.
3. 🧪 Test Private #methods
via Indirect Access (Advanced)
JavaScript’s #private
fields are not accessible via this['#method']
.
But with a hacky workaround using eval()
or by transforming the code with Babel, you can technically access it—but this is discouraged.
Example with Babel plugin:
npm install --save-dev @babel/plugin-proposal-private-methods
Then in your Jest config or Babel setup, enable loose mode. This exposes private methods as regular properties.
⚠️ Warning: This is fragile and breaks encapsulation. Use only if absolutely necessary.
🧠 Bonus: Refactor to Extract Pure Functions
If a private method is complex and needs direct testing, consider extracting it to a separate module:
// utils/math.js
export function square(n) {
return n * n;
}
// main class
import { square } from './utils/math.js';
class Calculator {
getSquarePlusOne(n) {
return square(n) + 1;
}
}
Now, you can test square()
directly without exposing internals of the class.
✅ Summary
Method | Works with | Recommended? |
---|---|---|
Test via public method | All types | ✅ Best practice |
Call _method() directly | Non-# methods | ✅ Acceptable |
Access #privateMethod() via hacks | # methods | ❌ Not recommended |
Extract to pure function | All types | ✅ Clean & testable |
🔚 Conclusion
Testing private methods in Jest isn’t always straightforward, especially with the modern #
syntax. The best approach is to focus on testing public behavior. If needed, you can call internal methods directly (if not truly private), or refactor your logic for better testability.
💡 Remember: tests should validate behavior, not implementation.