Skip to content

Commit

Permalink
Merge pull request #193 from boostcampwm-2024/feature-be-#129
Browse files Browse the repository at this point in the history
엣지 API 테스트코드 작성
  • Loading branch information
ezcolin2 authored Nov 18, 2024
2 parents 93fe456 + 268743e commit b38817b
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 16 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,4 @@ lerna-debug.log*

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
apps/backend/db.sqlite
Empty file added .vscode/settings.json
Empty file.
97 changes: 96 additions & 1 deletion apps/backend/src/edge/edge.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,120 @@
import { Test, TestingModule } from '@nestjs/testing';
import { EdgeController } from './edge.controller';
import { EdgeService } from './edge.service';
import { CreateEdgeDto } from './dtos/createEdge.dto';
import { EdgeResponseMessage } from './edge.controller';
import { EdgeNotFoundException } from '../exception/edge.exception';
import { Edge } from './edge.entity';
import { Node } from '../node/node.entity';

describe('EdgeController', () => {
let controller: EdgeController;
let edgeService: EdgeService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [EdgeController],
providers: [
{
provide: EdgeService,
useValue: {},
useValue: {
createEdge: jest.fn(),
deleteEdge: jest.fn(),
findEdges: jest.fn(),
},
},
],
}).compile();

controller = module.get<EdgeController>(EdgeController);
edgeService = module.get<EdgeService>(EdgeService);
});

it('컨트롤러 클래스가 정상적으로 인스턴스화된다.', () => {
expect(controller).toBeDefined();
});

describe('createEdge', () => {
it('엣지가 성공적으로 만들어진다', async () => {
const dto: CreateEdgeDto = { fromNode: 1, toNode: 3 };
const expectedResponse = {
message: EdgeResponseMessage.EDGE_CREATED,
};

jest.spyOn(edgeService, 'createEdge').mockResolvedValue(undefined);
const result = await controller.createEdge(dto);

expect(edgeService.createEdge).toHaveBeenCalledWith(dto);
expect(result).toEqual(expectedResponse);
});
});

describe('deleteEdge', () => {
it('id에 해당하는 엣지를 찾아 삭제한다.', async () => {
const id = 2;
const expectedResponse = {
message: EdgeResponseMessage.EDGE_DELETED,
};

const result = await controller.deleteEdge(id);

expect(edgeService.deleteEdge).toHaveBeenCalledWith(id);
expect(result).toEqual(expectedResponse);
});

it('id에 해당하는 엣지가 존재하지 않으면 NodeNotFoundException을 throw한다.', async () => {
jest
.spyOn(edgeService, 'deleteEdge')
.mockRejectedValue(new EdgeNotFoundException());

await expect(controller.deleteEdge(1)).rejects.toThrow(
EdgeNotFoundException,
);
});
});

describe('findEdges', () => {
it('모든 엣지 목록을 반환한다.', async () => {
const node3 = {
id: 3,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const node4 = {
id: 4,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const node5 = {
id: 5,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;

const expectedEdges = [
{ id: 1, fromNode: node3, toNode: node5 },
{ id: 2, fromNode: node3, toNode: node4 },
] as Edge[];
node3.outgoingEdges = [];

jest.spyOn(edgeService, 'findEdges').mockResolvedValue(expectedEdges);

await expect(controller.findEdges()).resolves.toEqual({
message: EdgeResponseMessage.EDGE_ALL_RETURNED,
edges: expectedEdges,
});
});
});
});
8 changes: 4 additions & 4 deletions apps/backend/src/edge/edge.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ export class EdgeController {
})
@Get('/')
@HttpCode(HttpStatus.OK)
async getNodes() {
const nodes = await this.edgeService.findEdges();
async findEdges() {
const edges = await this.edgeService.findEdges();
return {
message: EdgeResponseMessage.EDGE_ALL_RETURNED,
nodes: nodes,
edges: edges,
};
}

Expand All @@ -56,7 +56,7 @@ export class EdgeController {
@ApiOperation({ summary: '엣지를 삭제합니다.' })
@Delete('/:id')
@HttpCode(HttpStatus.OK)
async deleteNode(
async deleteEdge(
@Param('id', ParseIntPipe) id: number,
): Promise<{ message: string }> {
await this.edgeService.deleteEdge(id);
Expand Down
10 changes: 5 additions & 5 deletions apps/backend/src/edge/edge.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
// Column,
ManyToOne,
JoinColumn,
} from 'typeorm';
Expand All @@ -21,9 +21,9 @@ export class Edge {
@JoinColumn({ name: 'to_node_id' })
toNode: Node;

@Column({ nullable: true })
type: string;
// @Column({ nullable: true })
// type: string;

@Column({ nullable: true })
color: string;
// @Column({ nullable: true })
// color: string;
}
166 changes: 164 additions & 2 deletions apps/backend/src/edge/edge.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,191 @@ import { Test, TestingModule } from '@nestjs/testing';
import { EdgeService } from './edge.service';
import { EdgeRepository } from './edge.repository';
import { NodeRepository } from '../node/node.repository';
import { CreateEdgeDto } from './dtos/createEdge.dto';
import { Edge } from './edge.entity';
import { Node } from '../node/node.entity';
import { EdgeNotFoundException } from '../exception/edge.exception';

describe('EdgeService', () => {
let service: EdgeService;
let edgeRepository: jest.Mocked<EdgeRepository>;
let nodeRepository: jest.Mocked<NodeRepository>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
EdgeService,
{
provide: EdgeRepository,
useValue: {},
useValue: {
create: jest.fn(),
save: jest.fn(),
delete: jest.fn(),
findOneBy: jest.fn(),
find: jest.fn(),
},
},
{
provide: NodeRepository,
useValue: {},
useValue: {
save: jest.fn(),
findOneBy: jest.fn(),
},
},
],
}).compile();

service = module.get<EdgeService>(EdgeService);
edgeRepository = module.get(EdgeRepository);
nodeRepository = module.get(NodeRepository);
});

it('서비스 클래스가 정상적으로 인스턴스화된다.', () => {
expect(service).toBeDefined();
});

describe('createEdge', () => {
it('새로운 엣지를 만들어 노드와 노드를 연결하는 연결한다.', async () => {
const dto: CreateEdgeDto = { fromNode: 3, toNode: 5 };
const fromNode = {
id: 3,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const toNode = {
id: 5,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const edge = {
id: 1,
fromNode: fromNode,
toNode: toNode,
} as Edge;

jest
.spyOn(nodeRepository, 'findOneBy')
.mockResolvedValueOnce(fromNode) // 첫 번째 호출: fromNode
.mockResolvedValueOnce(toNode); // 두 번째 호출: toNode
jest.spyOn(edgeRepository, 'save').mockResolvedValue(edge);

const result = await service.createEdge(dto);

expect(result).toEqual(edge);
expect(edgeRepository.save).toHaveBeenCalledTimes(1);
expect(nodeRepository.findOneBy).toHaveBeenCalledTimes(2);
});
});

describe('deleteEdge', () => {
it('엣지를 성공적으로 삭제한다.', async () => {
jest
.spyOn(edgeRepository, 'delete')
.mockResolvedValue({ affected: true } as any);
jest.spyOn(edgeRepository, 'findOneBy').mockResolvedValue(new Edge());

await service.deleteEdge(1);

expect(edgeRepository.delete).toHaveBeenCalledWith(1);
});

it('삭제할 엣지가 존재하지 않으면 EdgeNotFoundException을 throw한다.', async () => {
jest
.spyOn(edgeRepository, 'delete')
.mockResolvedValue({ affected: false } as any);
await expect(service.deleteEdge(1)).rejects.toThrow(
EdgeNotFoundException,
);
});
});

describe('findEdges', () => {
it('존재하는 모든 엣지를 반환한다.', async () => {
const node3 = {
id: 3,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const node4 = {
id: 4,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const node5 = {
id: 5,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;
const node7 = {
id: 7,
x: 0,
y: 0,
title: 'Node Title',
page: null,
outgoingEdges: [],
incomingEdges: [],
} as Node;

const expectedEdgeList = [
{
id: 1,
fromNode: node3,
toNode: node5,
} as Edge,
{
id: 2,
fromNode: node3,
toNode: node4,
} as Edge,
{
id: 3,
fromNode: node3,
toNode: node7,
} as Edge,
];

jest.spyOn(edgeRepository, 'find').mockResolvedValue(expectedEdgeList);
const result = await service.findEdges();
expect(result).toEqual(expectedEdgeList);
expect(edgeRepository.find).toHaveBeenCalledTimes(1);
expect(edgeRepository.find).toHaveBeenCalledWith({
relations: ['fromNode', 'toNode'],
select: {
id: true,
fromNode: {
id: true,
},
toNode: {
id: true,
},
},
});
});

it('엣지가 없을 경우, 빈 배열을 던진다.', async () => {
jest.spyOn(edgeRepository, 'find').mockResolvedValue([]);
const result = await service.findEdges();
expect(result).toEqual([]);
});
});
});

0 comments on commit b38817b

Please sign in to comment.