question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How it is supposed to work with unit test?

See original GitHub issue

Hello there, I would like to test my controller (routing-controllers) but i don’t really know how to. Typedi is supposed to work like Angular2+ inject or similar. But when i use Container.set to override my model’s method used by the controller it’s seems to be broken. I need some hint to know how to do that. I think i do not test my controller like expected or maybe i don’t really understand Typedi Container and @Service injection implementation. It’s supposed to be usefull to avoid to mock db connection.

Thx a lot.

My spec

import 'reflect-metadata';
import { Application } from 'express';
import request from 'supertest';
import { createExpressServer, useContainer as useContainerRouting } from 'routing-controllers';
import { Container } from 'typedi';
import { ExampleController } from '../controllers/example.controller';
import { ExampleRepository } from '../repositories/example.repository';
import { ExampleModel } from '../models/example.model';

describe('GET', () => {
  let app: Application | null;

  beforeEach((_done: jest.DoneCallback) => {
    useContainerRouting(Container);
  });

  afterEach((_done: jest.DoneCallback) => {
    Container.reset();
    app = null;
  });

  it('should call model with proper id and returns model response', async () => {
    const EXAMPLE_ID_TEST: number = 1;

    app = createExpressServer({
      cors: true,
      controllers: [
        ExampleController
      ]
    });

    @Service()
    class TestModel {
      public getExampleById: any = jest.fn().mockImplementation((_id: number) => new Promise((resolve: any) => resolve({})));
    }

    Container.set(ExampleModel, new TestModel());

    const res: request.Response = await request(app).get(`/example/${EXAMPLE_ID_TEST}`);

    expect(res.body).toEqual({});
});

My controller

import { ExampleModel } from '../models/example.model';
import { TableTest } from '../entities/tabletest.entity';
import { JsonController, Get } from 'routing-controllers';

@JsonController('/example')
export class ExampleController {
  constructor(
    private readonly model: ExampleModel) {
  }
  @Get('/:id')
  public async getExample(@Param('id') id: number): Promise<TableTest> {
    return this.model.getExampleById(id);
  }
}

My Model

import { TableTest } from '../entities/tabletest.entity';
import { Service } from 'typedi';
import { OrmRepository } from 'typeorm-typedi-extensions';
import { NotFoundError } from 'routing-controllers';
import { ExampleRepository } from '../repositories/example.repository';

@Service()
export class ExampleModel {
  constructor(
    @OrmRepository()
    private readonly repository: ExampleRepository) {
  }

  public async getExampleById(id: number): Promise<TableTest> {
    const example: TableTest | undefined = await this.repository.findOneById(id);

    if (example === undefined) {
      throw new NotFoundError(`Example ${id} not found`);
    }

    return example;
  }
}

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

8reactions
MichalLytekcommented, Feb 22, 2018

General rule of thumb - keep it simple, stupid! 😉

Constructor injection in controllers is the best because it’s DI framework agnostic - you can just create the instance of the class and provide your mocks by yourself:

    let companyController: CompanyController;
    let bodyMock: ICategory;
    beforeEach(() => {
        companyController = new CompanyController(companyRepositoryMock, new Validator());
        bodyMock = new ICategory();
    });

So you make unit test of your controller methods like they would be the services, not connected to http (thanks to routing-controllers decorators). You check all the code flow in unit tests.

it("should login successfully when credentials are ok", async () => {
    const reponse: string = await userControler.loginUser(sessionMock, bodyMock);
    expect(reponse).to.equals("Logged succesfully!");
    expect(sessionMock.user.email).to.equals(bodyMock.email);
});

Then, you can make integration test. They check if the http server really works and return correct response:

it("should respond with 400 BadRequest when password is wrong", async () => {
    const credentials = {
        email: "test@test.pl",
        password: "wrongPassword"
    };
    const response = await chai.request(app)
        .post("/api/user/login")
        .send(credentials);

    expect(response).to.have.status(400);
    expect(response.body.message).to.equals("Wrong email or password!");
});

In integration test you can’t mock your code parts like services, etc. You need to check if all of your apps parts are working together. You check only the one good scenario that use all of the apps parts.

The only thing you should do is to to connect to local testing database, seed it with test data and maybe restore after each test that modified it. Mocks are allowed only to 3rd-party services like mail or Amazon S3 and I could be easily done with container.set or at the environment level (proxy server?).

So, @gmongin, don’t try to mock all the world when you are making http request to your app because you will test your mocks, not the real code 😆

0reactions
github-actions[bot]commented, Jul 31, 2020

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Unit Testing Tutorial – What is, Types & Test Example - Guru99
Unit testing allows the programmer to refactor code at a later date, and make sure the module still works correctly (i.e. Regression testing)....
Read more >
Unit Testing Tutorial: 6 Best Practices to Get Up To Speed
Unit Testing Best Practices · 1. Arrange, Act, Assert · 2. One Assert Per Test Method · 3. Avoid Test Interdependence · 4....
Read more >
What is unit testing and how do you do it? [duplicate]
Unit testing simply verifies that individual units of code (mostly functions) work as expected. Usually you write the test cases yourself, ...
Read more >
What Is Unit Testing? - SmartBear
Unit Testing is the process of checking small pieces of code to deliver information early and often, speeding your testing strategies, and reducing...
Read more >
What is Unit Testing? Definition from WhatIs.com - TechTarget
Unit testing is a software development process in which the smallest testable parts of an application, called units, are individually and independently ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found