inversify / InversifyJS

A powerful and lightweight inversion of control container for JavaScript & Node.js apps powered by TypeScript.

Home Page:http://inversify.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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"
  }}