Skip to content

Commit

Permalink
refactor: Test, Repository, HTTP Exception, Class Validator (#7) (#8)
Browse files Browse the repository at this point in the history
* test: 미작성 테스트 코드 삭제

* refactor: Group, Member repository 생성

* refactor: DB 이름 넣어주면서 살짝 변경

* refactor: Group

* refactor: Member

* refactor: HTTP Exception + Class validator

* fix: member.controller.spec.ts

* fix: Database query built from user-controlled sources
  • Loading branch information
w8385 authored Apr 11, 2024
1 parent dcb8d5d commit 7f83a49
Show file tree
Hide file tree
Showing 29 changed files with 704 additions and 308 deletions.
411 changes: 401 additions & 10 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
"@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.3.1",
"@typescript-eslint/typescript-estree": "^7.5.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"mongodb-memory-server": "^9.1.8",
"mongoose": "^8.3.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
Expand Down
20 changes: 0 additions & 20 deletions src/auth/auth.controller.spec.ts

This file was deleted.

18 changes: 0 additions & 18 deletions src/auth/auth.service.spec.ts

This file was deleted.

8 changes: 6 additions & 2 deletions src/database/database.providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ export const databaseProviders = [
provide: 'MONGODB_CONNECTION',
useFactory: (): Promise<typeof mongoose> => {
const configService = new ConfigService();
const uri = configService.get('MONGODB_URI');
return mongoose.connect(uri);
const uri = configService.get<string>('MONGODB_URI');
const dbName = configService.get<string>('MONGODB_DB_NAME');

return mongoose.connect(uri, {
dbName,
});
},
},
];
20 changes: 0 additions & 20 deletions src/event/event.controller.spec.ts

This file was deleted.

18 changes: 0 additions & 18 deletions src/event/event.service.spec.ts

This file was deleted.

9 changes: 9 additions & 0 deletions src/group/dto/create-group.dto.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsNotEmpty } from 'class-validator';

export class CreateGroupDto {
@IsNotEmpty()
@ApiProperty({
required: true,
description: '모임 이름',
example: 'SSU',
})
readonly name: string;

@IsNotEmpty()
@ApiProperty({
required: true,
description: '모임 설명',
example: '숭실대학교 학생들의 모임',
})
readonly description: string;

@IsNotEmpty()
@ApiProperty({
required: true,
description: '모임장 사용자의 ObjectId',
example: '60f4b3b3b3b3b3b3b3b3b3b3',
})
readonly manager: string;

@ApiProperty({
required: false,
description: '부모임장 사용자의 ObjectId와 권한',
example: [
{
Expand All @@ -36,6 +44,7 @@ export class CreateGroupDto {
];

@ApiProperty({
required: false,
description: '모임원 사용자의 ObjectId',
example: ['60f4b3b3b3b3b3b3b3b3b3'],
})
Expand Down
61 changes: 47 additions & 14 deletions src/group/group.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,60 @@
import { GroupController } from './group.controller';
import { GroupService } from './group.service';
import { HydratedDocument, Model } from 'mongoose';
import { Group } from './interfaces/group.interface';
import { Test, TestingModule } from '@nestjs/testing';
import { DatabaseModule } from '../database/database.module';
import { groupProvider } from './group.provider';
import { MongoMemoryServer } from 'mongodb-memory-server';
import * as process from 'process';
import { Group } from './entities/group.entity';
import mongoose from 'mongoose';
import { CreateGroupDto } from './dto/create-group.dto';
import { GroupRepository } from './group.repository';

describe('GroupController', () => {
let groupController: GroupController;
let groupService: GroupService;
let groupModel: Model<Group>;
let mongoServer: MongoMemoryServer;

beforeEach(async () => {
groupService = new GroupService(groupModel);
groupController = new GroupController(groupService);
beforeAll(async () => {
mongoServer = await MongoMemoryServer.create();
process.env.MONGODB_URI = mongoServer.getUri();

const module: TestingModule = await Test.createTestingModule({
imports: [DatabaseModule],
controllers: [GroupController],
providers: [GroupService, ...groupProvider, GroupRepository],
}).compile();

groupService = module.get<GroupService>(GroupService);
groupController = module.get<GroupController>(GroupController);
});

describe('findAll', () => {
it('should return an array of groups', async () => {
const result: HydratedDocument<any> = [
{ _id: 1, name: 'Group 1' },
{ _id: 2, name: 'Group 2' },
];
jest.spyOn(groupService, 'findAll').mockImplementation(() => result);
describe('create', () => {
it('should return a group', async () => {
const group: CreateGroupDto = {
name: 'Group 1',
description: 'Group 1 description',
manager: 'user1',
subManagers: null,
members: ['user1', 'user2'],
};

const result: Group = await groupService.create(group);

expect(await groupController.findAll()).toBe(result);
jest.spyOn(groupService, 'create').mockImplementation(async () => result);

expect(await groupController.create(group)).toBe(result);
expect(result).toHaveProperty('name', group.name);
expect(result).toHaveProperty('description', group.description);
expect(result).toHaveProperty('manager', group.manager);
expect(result).toHaveProperty('subManagers', group.subManagers);
expect(result).toHaveProperty('members', group.members);
});
});

afterAll(async () => {
await mongoose.connection.dropDatabase();
await mongoose.connection.close();
await mongoServer.stop();
});
});
11 changes: 7 additions & 4 deletions src/group/group.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import {
Param,
Patch,
Post,
UseFilters,
} from '@nestjs/common';
import { GroupService } from './group.service';
import { CreateGroupDto } from './dto/create-group.dto';
import { UpdateGroupDto } from './dto/update-group.dto';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { HttpExceptionFilter } from '../http-exception.filter';

@ApiTags('Group')
@Controller('group')
@UseFilters(HttpExceptionFilter)
export class GroupController {
constructor(private readonly groupService: GroupService) {}

Expand Down Expand Up @@ -58,16 +61,16 @@ export class GroupController {
summary: '모든 모임 삭제',
description: '모든 모임을 삭제합니다.',
})
removeAll() {
return this.groupService.removeAll();
deleteAll() {
return this.groupService.deleteAll();
}

@Delete(':id')
@ApiOperation({
summary: '모임 삭제',
description: '특정 모임을 삭제합니다.',
})
remove(@Param('id') id: string) {
return this.groupService.remove(id);
delete(@Param('id') id: string) {
return this.groupService.delete(id);
}
}
3 changes: 2 additions & 1 deletion src/group/group.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { GroupService } from './group.service';
import { GroupController } from './group.controller';
import { groupProvider } from './group.provider';
import { DatabaseModule } from '../database/database.module';
import { GroupRepository } from './group.repository';

@Module({
imports: [DatabaseModule],
controllers: [GroupController],
providers: [GroupService, ...groupProvider],
providers: [GroupService, ...groupProvider, GroupRepository],
})
export class GroupModule {}
39 changes: 39 additions & 0 deletions src/group/group.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Inject, Injectable } from '@nestjs/common';
import { Model } from 'mongoose';
import { Group } from './interfaces/group.interface';
import { CreateGroupDto } from './dto/create-group.dto';
import { UpdateGroupDto } from './dto/update-group.dto';

@Injectable()
export class GroupRepository {
constructor(
@Inject('GROUP_MODEL')
private readonly groupModel: Model<Group>,
) {}

create(createGroupDto: CreateGroupDto): Promise<Group> {
return this.groupModel.create(createGroupDto);
}

findAll(): Promise<Group[]> {
return this.groupModel.find().exec();
}

findOne(id: string): Promise<Group> {
return this.groupModel.findById(id).exec();
}

update(id: string, updateGroupDto: UpdateGroupDto): Promise<Group> {
return this.groupModel
.findByIdAndUpdate(id, updateGroupDto, { new: true })
.exec();
}

delete(id: string) {
this.groupModel.findByIdAndDelete(id);
}

deleteAll() {
this.groupModel.deleteMany({}).exec();
}
}
24 changes: 0 additions & 24 deletions src/group/group.service.spec.ts

This file was deleted.

Loading

0 comments on commit 7f83a49

Please sign in to comment.