Search code examples
mysqlnestjstddprisma

Same tests for controllers and services in NestJS API (Test Driven Development)


I'm developing a NestJS-based API using Prisma and MySQL for the database. As I'm new to Test Driven Development (TDD), I want to start incorporating tests into my project. I have successfully written tests for the UsersService but I'm confused about how to approach testing the corresponding UsersController. Additionally, I'm uncertain about the distinction between unit tests and integration tests. Below, I'll provide the relevant code snippets for my UsersService, UsersController, and the tests I've written so far.

Prisma Schema:

enum Role {
  ADMIN
  AMBASSADOR
  USER
}

model User {
  id        String   @id @default(uuid())
  email     String   @unique
  username  String   @unique
  firstname String
  lastname  String
  password  String
  role      Role     @default(USER)
  createdAt DateTime @default(now()) @map("created_at")
  updatedAt DateTime @updatedAt @map("updated_at")

  @@map("users")
}

UsersService (relevant parts):

async create(createUserDto: CreateUserDto): Promise<User> {
  // Validation methods: _validateUsername, _validateEmail, etc.

  const createdUser = await this.prisma.user.create({
    data: {
      ...createUserDto,
      password: await this._hashPassword(createUserDto.password),
    },
  });

  // Returning selected user properties
  return {
    id: createdUser.id,
    username: createdUser.username,
    email: createdUser.email,
    firstname: createdUser.firstname,
    lastname: createdUser.lastname,
    role: createdUser.role,
    createdAt: createdUser.createdAt,
    updatedAt: createdUser.updatedAt,
  };
}

UsersController (relevant part):

@Post()
@HttpCode(HttpStatus.CREATED)
create(@Body() createUserDto: CreateUserDto) {
  return this.usersService.create(createUserDto);
}

Specific Questions:

  • For the UsersController, what are the recommended approaches for writing tests? How do they differ from the tests written for the UsersService?
  • What is the distinction between unit tests and integration tests? Are the tests I've written for UsersService considered unit tests or something else?

Solution

  • With unit tests you can test each method independently, for example if your controller method is calling and returning a method of your service you should test if your method of controller is calling the method of your service in your unit test.

    Integration tests are more about testing the code as a whole, you usually don't use mocks and try to test the whole flow of your application and you use real database and everything. For example you can test user stories like login and logout, register and create a profile etc.

    Personally I write unit tests first while working with TDD. I write integration tests afterwards if I feel like I need any.