'Can't define entity in controller's unit test
I want to write a unit test for a controller in NestJS which uses the service. Service uses an entity and typeorm to getting data from postgres.
controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { EmissionsWeldingController } from '../EmissionsWelding.controller';
describe('EmissionsWeldingController', () => {
let controller: EmissionsWeldingController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [EmissionsWeldingController],
}).compile();
controller = module.get<EmissionsWeldingController>(EmissionsWeldingController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
It failed with an error: Nest can't resolve dependencies of the EmissionsWeldingController (?). Please make sure that the argument EmissionsWeldingService at index [0] is available in the RootTestModule context.
When I define my service and entity
import { Test, TestingModule } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';
import { EmissionsWeldingController } from '../EmissionsWelding.controller';
import { Mark, Substance, WorkType, WorkSpecification, InputField, SummaryValue } from '../EmissionsWelding.entity';
import { EmissionsWeldingService } from '../EmissionsWelding.service';
describe('EmissionsWeldingController', () => {
let controller: EmissionsWeldingController;
let service: EmissionsWeldingService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [TypeOrmModule.forFeature([Mark, Substance, WorkType, WorkSpecification, InputField, SummaryValue])],
controllers: [EmissionsWeldingController],
providers: [EmissionsWeldingService],
}).compile();
controller = module.get<EmissionsWeldingController>(EmissionsWeldingController);
service = module.get<EmissionsWeldingService>(EmissionsWeldingService);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
It's failing with an error: Nest can't resolve dependencies of the MarkRepository (?). Please make sure that the argument Connection at index [0] is available in the TypeOrmModule context.
How should I define providers and entities without getting above error?
service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { GetResultDto } from './dto/GetResult.dto';
import { InputField, Mark, Substance, SummaryValue, WorkSpecification, WorkType } from './EmissionsWelding.entity';
@Injectable()
export class EmissionsWeldingService {
constructor(
@InjectRepository(Mark)
private markRepository: Repository<Mark>,
@InjectRepository(Substance)
private substanceRepository: Repository<Substance>,
@InjectRepository(WorkSpecification)
private workSpecificationRepository: Repository<WorkSpecification>,
@InjectRepository(WorkType)
private workTypeRepository: Repository<WorkType>,
@InjectRepository(InputField)
private inputFieldRepository: Repository<InputField>,
@InjectRepository(SummaryValue)
private summaryValueRepository: Repository<SummaryValue>,
) {}
async getMarks(work_type_id: number, work_specification_id: number): Promise<Mark[]> {
return await this.markRepository.find({ where: { work_type_id, work_specification_id } });
}
async getSubstances(): Promise<Substance[]> {
return await this.substanceRepository.find();
}
async getWorkSpecifications(): Promise<WorkSpecification[]> {
return await this.workSpecificationRepository.find();
}
async getWorkTypes(): Promise<WorkType[]> {
return await this.workTypeRepository.find();
}
async getInputFields(): Promise<WorkType[]> {
return await this.inputFieldRepository.find();
}
async getSummaryValues(mark_id: number, substance_id: number): Promise<SummaryValue[]> {
return await this.summaryValueRepository.find({ where: { mark_id, substance_id } });
}
async getResult(body: GetResultDto): Promise<GetResultDto[]> {
const result = [];
const { mark_id, input_fields_values } = body;
const substances = await this.getSubstances();
let currentSummaryValue;
for (let i = 0; i <= substances.length - 1; i++) {
currentSummaryValue = await this.getSummaryValues(mark_id, i + 1);
result.push({
code: substances[i].code,
name: substances[i].name,
year:
((input_fields_values.year * currentSummaryValue[0].value) / 10 ** 6) *
(1 - (input_fields_values.clean ? input_fields_values.clean : 0)),
second:
((currentSummaryValue[0].value * input_fields_values.hour) / 3600) *
(1 - (input_fields_values.clean ? input_fields_values.clean : 0)),
});
}
return result;
}
}
controller.ts
import { Body, Controller, Get, Post, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { GetResultDto } from './dto/GetResult.dto';
import { EmissionsWeldingService } from './EmissionsWelding.service';
@ApiTags('EmissionsWelding')
@Controller('EmissionsWelding')
export class EmissionsWeldingController {
constructor(private emissionsWeldingService: EmissionsWeldingService) {}
@Get('getMarks')
getMarks(@Query('work_type_id') work_type_id: number, @Query('work_specification_id') work_specification_id: number) {
return this.emissionsWeldingService.getMarks(work_type_id, work_specification_id);
}
@Get('getSubstances')
getSubstances() {
return this.emissionsWeldingService.getSubstances();
}
@Get('getWorkSpecifications')
getWorkSpecifications() {
return this.emissionsWeldingService.getWorkSpecifications();
}
@Get('getWorkTypes')
getWorkTypes() {
return this.emissionsWeldingService.getWorkTypes();
}
@Get('getInputFields')
getInputFields() {
return this.emissionsWeldingService.getInputFields();
}
@Post('getResult')
getResult(@Body() body: GetResultDto) {
return this.emissionsWeldingService.getResult(body);
}
}
Solution 1:[1]
You need to provide a mock for every repository that is injected into your service.
This answer provides the necessary detail so please give it an upvote: https://stackoverflow.com/a/55366343/588734
describe('EmissionsWeldingController', () => {
let controller: EmissionsWeldingController;
let service: EmissionsWeldingService;
let markRepositoryMock: MockType<Repository<Mark>>;
// repeat for every repository let __RepositoryMock: MockType<Repository<__>>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [EmissionsWeldingController],
providers: [
EmissionsWeldingService,
{
provide: getRepositoryToken(Mark),
useValue: jest.fn(() => ({
findOne: jest.fn(entity => entity),
// provide a mock for each function you are calling
}))
},
// repeat for every mock
],
}).compile();
controller = module.get<EmissionsWeldingController>(EmissionsWeldingController);
service = module.get<EmissionsWeldingService>(EmissionsWeldingService);
markRepositoryMock = module.get(getRepositoryToken(Mark));
// repeat for every mock repository
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Eamonn McEvoy |