Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Error trying to instantiate controller in a test (Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext)) #360

Open
marcosdipaoloSV opened this issue Feb 25, 2021 · 1 comment

Comments

@marcosdipaoloSV
Copy link

I'm trying to write a unit test for a controller that has an injected service at the constructor, that's why (unlike the docs where controllers are instantiated with the new keyword in a test) i need to instantiate it with the container.
The controller extends the BaseHttpController from inversify-express-utils I'm failing trying to do:

Test

import { expect } from "chai"
import { container } from '../../src/container/inversify.config'
import { HealthControllerV1 } from "../../src/controllers/v1/HealthControllerV1"
import { results } from "inversify-express-utils"

describe("ExampleController", () => {
    let controller: HealthControllerV1

    beforeEach(() => {
        controller = container.get<HealthControllerV1>(HealthControllerV1)
    })

    describe("Health", () => {
        it("should return 200 status with Json response", async () => {
            const response = controller.health()
            expect(response).to.be.an.instanceof(results.JsonResult)
        })
    })
})  

Container:

import { Container } from "inversify";
import { HealthControllerV1 } from "../controllers/v1/HealthControllerV1";
import { GoalsService, IGoalsService } from "../services/GoalsService";

const container = new Container()

container.bind<HealthControllerV1>(HealthControllerV1).toSelf()
container.bind<IGoalsService>('goalsService').to(GoalsService)

export { container }

Controller:

import 'reflect-metadata'
import { BaseHttpController, controller, httpGet, interfaces, results } from 'inversify-express-utils'
import { inject } from 'inversify'
import { IGoalsService } from '../../services/GoalsService'

@controller('/v1/health')
export class HealthControllerV1 extends BaseHttpController implements interfaces.Controller {

    constructor(@inject('goalsService') private goalsService: IGoalsService){super()}
    
    @httpGet('/')
    health(): results.JsonResult {
        this.goalsService.log('111')
        return this.json({ msg: 'OK' })
    }
}   

Error:

HealthControllerV1
    Health
      1) "before each" hook for "should return 200 status with Json response"


  0 passing (8ms)
  1 failing

  1) HealthControllerV1
       "before each" hook for "should return 200 status with Json response":
     Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext)

My Environment

"inversify": "^5.0.5",
"inversify-express-utils": "^6.3.2",
"node": "12.20.0"
"chai": "^4.3.0",
"express": "^4.17.1",
"mocha": "^8.3.0",
"reflect-metadata": "^0.1.13",

Stack trace

 Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext)
      at _validateActiveBindingCount (node_modules/inversify/lib/planning/planner.js:63:23)
      at _getActiveBindings (node_modules/inversify/lib/planning/planner.js:49:5)
      at _createSubRequests (node_modules/inversify/lib/planning/planner.js:92:26)
      at /home/marcosdipaolo/Documents/dev/goals-backend/node_modules/inversify/lib/planning/planner.js:116:17
      at Array.forEach (<anonymous>)
      at /home/marcosdipaolo/Documents/dev/goals-backend/node_modules/inversify/lib/planning/planner.js:115:26
      at Array.forEach (<anonymous>)
      at _createSubRequests (node_modules/inversify/lib/planning/planner.js:95:20)
      at Object.plan (node_modules/inversify/lib/planning/planner.js:137:9)
      at /home/marcosdipaolo/Documents/dev/goals-backend/node_modules/inversify/lib/container/container.js:319:37
      at Container._get (node_modules/inversify/lib/container/container.js:312:44)
      at Container.get (node_modules/inversify/lib/container/container.js:232:21)
      at Context.<anonymous> (test/unit/health.test.ts:10:32)
      at processImmediate (internal/timers.js:461:21)

thanks a lot

@marcosdipaoloSV marcosdipaoloSV changed the title Error trying to instantiate controller in a test (extending BaseHttpController, using inversify-express-utils) Error trying to instantiate controller in a test (Error: No matching bindings found for serviceIdentifier: Symbol(HttpContext)) Feb 25, 2021
@marcosdipaoloSV
Copy link
Author

For some reason i neither know nor understand, in a test you need to mock the httpContext (the one you get from BaseHttpController) and bind it to the container before you try to instantiate the controller

The mocked httpContext

import { mockReq, mockRes } from 'sinon-express-mock'
import { interfaces } from "inversify-express-utils"
import { container } from '../src/container/inversify.config'

const mockRequest = mockReq()
const mockResponse = mockRes()

const mockUser: interfaces.Principal = {
    details: "",
    isAuthenticated: () => Promise.resolve(true),
    isResourceOwner: () => Promise.resolve(true),
    isInRole: () => Promise.resolve(true)
}

export const mockedHttpContext: interfaces.HttpContext = {
    request: mockRequest,
    response: mockResponse,
    user: mockUser,
    container
}

The test

import { expect } from "chai"
import { container } from '../../src/container/inversify.config'
import { HealthControllerV1 } from "../../src/controllers/v1/HealthControllerV1"
import { results, interfaces } from "inversify-express-utils"
import { mockedHttpContext } from '../mockedHttpContext'

describe("HealthControllerV1", () => {
    let controller: HealthControllerV1
    
    container.bind<interfaces.HttpContext>(Symbol.for("HttpContext")).toConstantValue(mockedHttpContext)
    
    beforeEach(() => {
        controller = container.get<HealthControllerV1>(HealthControllerV1)
    })

    describe("Health", () => {
        it("should return 200 status with Json response", async () => {
            const response = controller.health()
            expect(response).to.be.an.instanceof(results.JsonResult)
        })
    })
})      

@PodaruDragos PodaruDragos transferred this issue from inversify/InversifyJS Jan 28, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant