I am developing an API in Nest using Knex:
import { Injectable, NotFoundException } from '@nestjs/common'
import { InjectKnex, Knex } from 'nestjs-knex'
import { ICreatePersonData, IUpdatePersonData, Person } from './types'
import { PeopleUtils } from './people.utils'
import { ErrorsService } from 'src/shared/utils/errors.service'
@Injectable()
export class PeopleRepository {
constructor(
@InjectKnex() private readonly knex: Knex,
private peopleUtils: PeopleUtils,
private errorsService: ErrorsService
) {}
async createPerson(createPersonData: ICreatePersonData): Promise<Person> {
try {
const {
name,
surname,
personType,
cpf,
cnpj,
birthDate,
address,
number,
city,
state,
zipCode,
complement,
neighborhood,
email,
phone,
cellphone
} = createPersonData
const [personId] = await this.knex('people').insert({
name,
surname,
person_type: personType,
cpf,
cnpj,
birth_date: birthDate,
address,
number,
city,
state,
zip_code: zipCode,
complement,
neighborhood,
email,
phone,
cellphone
})
const person = await this.findPersonById(personId)
return person
} catch (error) {
throw this.errorsService.handleErrors(
error,
'#Não foi possível criar a pessoa',
'repository/createPerson'
)
}
}
I am trying to perform unit tests, but I am having difficulties mocking Knex. The test file looks like this (I am using Jest):
import { Test, TestingModule } from '@nestjs/testing'
import { PeopleUtils } from '../people.utils'
import {
InternalServerErrorException
} from '@nestjs/common'
import { ICreatePersonData, IUpdatePersonData, Person } from '../types'
import { ValidatesService } from 'src/shared/utils/validates.service'
import { CreatePersonDto } from '../dto/create-person.dto'
import { UpdatePersonDto } from '../dto/update-person.dto'
import { PeopleRepository } from '../people.repository'
import { ErrorsService } from 'src/shared/utils/errors.service'
import { Knex } from 'knex'
import { InjectKnex, KnexModule, KnexModuleOptions } from 'nestjs-knex'
const knexModuleProvider = {
provide: 'KnexConnection',
useValue: KnexModule.forRoot(mysqlConfig)
}
describe('PeopleRepository', () => {
let peopleRepository: PeopleRepository
let mockPeopleUtils: PeopleUtils
let mockErrorsService: ErrorsService
let mockKnex: KnexModule
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PeopleRepository,
{
provide: PeopleUtils,
useValue: {
createPeopleArrayFromDB: jest
.fn()
.mockReturnValue([person1, person2])
}
},
{
provide: ErrorsService,
useValue: {
handleErrors: jest
.fn()
.mockReturnValue(new InternalServerErrorException())
}
},
knexModuleProvider
]
}).compile()
peopleRepository = module.get<PeopleRepository>(PeopleRepository)
mockPeopleUtils = module.get<PeopleUtils>(PeopleUtils)
mockErrorsService = module.get<ErrorsService>(ErrorsService)
mockKnex = module.get('KnexConection')
})
it('should be defined', () => {
expect(peopleRepository).toBeDefined()
expect(mockPeopleUtils).toBeDefined()
expect(mockErrorsService).toBeDefined()
expect(mockKnex).toBeDefined()
})
describe('createPerson', () => {
it('should return a Person', async () => {
//Arrange
const createPersonData: ICreatePersonData = createPersonData1
const expected: Person = person1
jest
.spyOn(mockErrorsService, 'handleErrors')
.mockReturnValue(new InternalServerErrorException())
//Act
const result = await peopleRepository.createPerson(createPersonData)
//Assert
expect(result).toBeDefined()
expect(result).toBeInstanceOf(Array)
expect(result).toEqual(expected)
})
At this moment, the code looks like this, but I have tried so many things that I think I don't even know what I'm doing anymore.
Has anyone done this and can help me?
It doesn't help, for example, to import the knexModule in the imports section because Nest doesn't allow mocking functions in imported modules.