NO_CONTROLLERS_FOUND error when building server from Jest.beforeEach
gacastro opened this issue · comments
I have an InversifyExpressServer app that holds in memory (cache) reference values retrieved from calling a couple of APIs. When I'm doing my tests, most of the times I don't want the cache running so there is no state between tests. But for the cache tests I obviously need it running. The way I want to achieve this is by instantiating the container, server and app at the describe level or at the beforeEach level, respectively
Here's a pseudo code (fake) of what I'm doing so my point can become clearer. This is the setup of a test when I need the cache running:
import {setupContainer} from ....
import {buildServer} from ....
import request from supertest
describe("testing out if the app runs with the cache", () => {
const container = new Container();
setupContainer(container);
const app = buildServer(container).build();
test("this test will setup the cache considering its the first one to run", () => {
request(app).get("/some-path");
expect(referenceApi).toHaveBeenCalled();
});
test("this test will read from the cache", () => {
request(app).get("/some-path");
doNOT.expect(referenceApi).toHaveBeenCalled();
});
});
This is the setup of a test when I don't need the cache running:
import {setupContainer} from ....
import {buildServer} from ....
import request from supertest
describe("testing out if the app runs without a cache", () => {
let app: Application;
beforeEach(() => {
const container = new Container();
setupContainer(container);
app = buildServer(container).build();
})
test("this test will setup a cache", () => {
request(app).get("/some-path");
expect(referenceApi).toHaveBeenCalled();
});
test("this test will setup a cache", () => {
request(app).get("/some-path");
expect(referenceApi).toHaveBeenCalled();
});
});
As you have probably guessed it, I have the configuration of the server and the container in different modules. The setupContainer
is a function that takes in the container and returns void. The buildServer
is a function that takes in a Container and returns the InversifyExpressServer
.
My controllers are decorated with @controller
and the class is exported (as seen in your examples). I'm also importing the controller file only once as per recommendation. And I do it in the setupContainer
module.
The issue
I have is that when I instantiate the elements inside the beforeEach level I get NO_CONTROLLERS_FOUND error. But when I instantiate them at the describe level I don't get the error.
I have tried the cleanUpMetadata
. I have tried importing the controllers in all three files (test, container and server) or in one at a time. The problem persisted. Then I started looking into the error more closely and saw this in your library.
Solution
Was that I gave it a go at starting the server with forceControllers: false
as suggested and to my surprise both of my code samples worked. Plus, when I actually run the application it continues to work.
My request is
If you can explain to me why its working when apparently no controller is binded to the container?
Environment
- Node 16, npm 8
{"dependencies": {
"@aws-sdk/client-lambda": "^3.105.0",
"@aws-sdk/client-sns": "^3.18.0",
"ajv": "^6.12.6",
"body-parser": "^1.19.0",
"date-fns": "^2.29.2",
"express": "^4.17.1",
"http-status-codes": "^1.4.0",
"inversify": "^6.0.1",
"inversify-express-utils": "^6.3.2",
"node-fetch": "^2.6.1",
"object-hash": "^2.2.0",
"reflect-metadata": "^0.1.13",
"serverless-http": "^2.7.0",
"uuid": "^8.3.2"
}}