TL;DR: Use bracket notation to Access private
properties
expect(inst["_somePrivateProp"]).toBe("foo"); // OK
Disclaimer
This is not a lengthy discussion. But a small reference type post. There are other (lengthy) posts that go into the details. I like it short.
Introduction
There is some ongoing debate about testing private members (methods, fields, properties, ...). In my opinion there are occasions where it is useful to do that.
In your test code you extend those classes and write wrappers/accessors to access these members. Then you actually test your derived class. This is cumbersome and also changes the semantics of the class you want to test. It is not possible to directly inspect/test private members in languages like C#. But there is a common inheritance based workround, where private members are made protected.
private
members appear to be intended to be accessed in derived classes. Which is not the case!
JavaScript/TypeScript
JavaScript/TypeScript does not require you to do that (at least for TypeScript private
members, not for ES private (#
) class fields).
// mod.ts
export class SomeClass {
private _somePrivateProp = "foo";
}
JavaScript does not care if your member is marked private
by TypeScript.
The TypeScript compiler enforces that you don't access private
members from outside the class using dot notation (inst.prop
).
But it is possible to access the property using bracket notation (inst["prop"]
).
// mod.test.ts
import {SomeClass} from "./mod.ts";
test("privatePropIsFoo", () => {
const inst = new SomeClass();
expect(inst._somePrivateProp).toBe("foo"); // TS2341: Property '_somePrivateProp' is private and only accessible within class 'SomeClass'.
expect(inst["_somePrivateProp"]).toBe("foo"); // OK
})
This is great because refactoring tools still work. And it saves a lot of redundant code.
A caveat
jest.spy(inst, "_privateMethod")
will not work, because TypeScript enforces that only public methods are spied on. The simplest workaround is to cast inst as any
. Until there is a Utility Type that treats all members as public (as already suggested).
Top comments (0)