Overriding Singletons from TSyringe within Jest Tests
You might encounter some issues while trying to override singletons from TSyringe in Jest tests. Here is a quick post to help you to fix them.
Quick Overview of TSyringe
Dependency Injection (often abbreviated as D.I.), when correctly used, is one of the tools used to create modular, maintainable & testable applications. Every language has its own D.I. libraries. For example Scala users may use the powerful macros from MacWire.
Dependency Injection is a design pattern used to implement Inversion of Control. One of the advantage is to not have to manually wire classes together.
Overriding injectables & usage within Jest
The library also allows us to create children dependency injection containers. Then it becomes easy to override some injectables during our tests:
Note: writing two times
.register<Foo>(Foo, NewFoo) is not a mistake. The second one is the injection token
while the first one is here to constraint
NewFoo to have the same shape as
Foo during compilation. The generic type
parameter can be omitted if you don’t want this additional security layer (although recommended).
Issues with Singletons
TSyringe supports singletons, useful if you don’t want to create a new instance every time you call
Unfortunately if you want to override a singleton, it will screw up everything, and you will not receive an error/warning from TSyringe (as of 4.3.0). This is because when you register a class as a singleton it is done within the global container (i.e. if you try to override it in a child container, then at the end it is overridden in all containers).
We can easily reproduce it with the following test:
Here is the associated output from Jest, where we can see the error:
As mentioned in the documentation we can easily fix this issue by adding the following snippet at the top of our test file:
Bonus point: if you do not want to add it at the top of all your test files, then you can instead add it to a file
referenced by the
setupFilesAfterEnv option from Jest
Thoughts about using Mocks from Jest
Mocks from Jest (Manual & ES6 classes) are really powerful, well-supported & documented. Depending on your needs you may choose between the two strategies or combine them. One nice advantage of TSyringe is the ability to automatically wire all the dependencies in complex applications.