Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/apis/auth/__test__/auth.resolver.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ const EXAMPLE_USER: User = {
password: 'exampleUserPassword',
phone: 'exampleUserPhone',
image: 'exampleUserImage',
createAt: new Date(),
deleteAt: new Date(),
updateAt: new Date(),
createdAt: new Date(),
deletedAt: new Date(),
updatedAt: new Date(),
dogs: [null],
reservation: [null],
};
Expand Down
140 changes: 93 additions & 47 deletions src/apis/auth/__test__/auth.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { CACHE_MANAGER, UnprocessableEntityException } from '@nestjs/common';
import {
CACHE_MANAGER,
UnauthorizedException,
UnprocessableEntityException,
} from '@nestjs/common';
import { Cache } from 'cache-manager';
import { UsersService } from 'src/apis/users/user.service';
import { User } from 'src/apis/users/entities/user.entity';
import { AuthService } from '../auth.service';
import { IContext } from 'src/commons/interface/context';
import { JwtService } from '@nestjs/jwt';
import * as httpMocks from 'node-mocks-http';
import { MockUsersRepository } from './auth.mocking.dummy';
import { MailerModule } from '@nestjs-modules/mailer';

jest.mock('../auth.service');

Expand All @@ -20,45 +21,51 @@ const EXAMPLE_USER: User = {
password: 'exampleUserPassword',
phone: 'exampleUserPhone',
image: 'exampleUserImage',
createAt: new Date(),
deleteAt: new Date(),
updateAt: new Date(),
createdAt: new Date(),
deletedAt: new Date(),
updatedAt: new Date(),
dogs: [null],
reservation: [null],
};

describe('AuthResolver', () => {
let authService: AuthService;
let usersService: UsersService;
let jwtService: JwtService;
let cache: Cache;
let context: IContext;
let jwt: JwtService;
let cacheManager: Cache;

const context: IContext = {
req: httpMocks.createRequest(),
res: httpMocks.createResponse(),
};
context.req.user = new User();
context.req.user.id = EXAMPLE_USER.id;
const email = EXAMPLE_USER.email;
const password = EXAMPLE_USER.password;
const process = {
env: {
JWT_ACCESS_KEY: 'exampleAccess',
JWT_REFRESH_KEY: 'exampleRefresh',
},
};

beforeEach(async () => {
jest.clearAllMocks();
const usersModule: TestingModule = await Test.createTestingModule({
imports: [
MailerModule.forRootAsync({
useFactory: () => ({
transport: {
service: 'Gmail',
host: process.env.EMAIL_HOST,
port: Number(process.env.DATABASE_PORT),
secure: false,
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
},
}),
}),
],
const modules: TestingModule = await Test.createTestingModule({
providers: [
AuthService,
UsersService,
{
provide: getRepositoryToken(User),
useClass: MockUsersRepository,
provide: UsersService,
useValue: {
findOneByEmail: jest.fn(() => EXAMPLE_USER),
create: jest.fn(() => EXAMPLE_USER),
},
},
{
provide: JwtService,
useValue: {
verify: jest.fn(() => 'EXAMPLE_TOKEN'),
},
},
{
provide: CACHE_MANAGER,
Expand All @@ -69,22 +76,13 @@ describe('AuthResolver', () => {
},
],
}).compile();
const authModule: TestingModule = await Test.createTestingModule({
providers: [AuthService],
}).compile();

usersService = usersModule.get<UsersService>(UsersService);
authService = authModule.get<AuthService>(AuthService);
cache = usersModule.get(CACHE_MANAGER);
context = {
req: httpMocks.createRequest(),
res: httpMocks.createResponse(),
};
authService = modules.get<AuthService>(AuthService);
usersService = modules.get<UsersService>(UsersService);
jwt = modules.get<JwtService>(JwtService);
cacheManager = modules.get(CACHE_MANAGER);
});

const email = EXAMPLE_USER.email;
const password = EXAMPLE_USER.password;

describe('login', () => {
it('의존성주입한 usersService 에서 email로 찾아오기', async () => {
jest
Expand Down Expand Up @@ -129,10 +127,58 @@ describe('AuthResolver', () => {
});

describe('logout', () => {
//
});
const req = context.req;
it('토큰 증명해서 로그아웃 인가', async () => {
const req = {
headers: {
authorization: 'Bearer ACCESS_TOKEN',
cookie: 'refreshToken=REFRESH_TOKEN',
},
};

describe('restoreAccessToken', () => {
//
try {
const accessToken = await req.headers['authorization'].replace(
'Bearer ',
'',
);
const refreshToken = await req.headers['cookie'].split(
'refreshToken=',
)[1];

// accessToken 토큰
const jwtAccessKey = jwt.verify(accessToken);

// refresh 토큰
const jwtRefreshKey = jwt.verify(refreshToken);

await cacheManager.set(`accessToken:${accessToken}`, 'accessToken', {
ttl: jwtAccessKey['exp'] - jwtAccessKey['iat'],
});

await cacheManager.set(`refreshToken:${refreshToken}`, 'refreshToken', {
ttl: jwtRefreshKey['exp'] - jwtRefreshKey['iat'],
});

expect(jwt.verify).toBeCalled();

return '로그아웃에 성공했습니다.';
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error.message).toBe('로그아웃을 실패했습니다.');
throw new UnauthorizedException('로그아웃을 실패했습니다.');
}
});

describe('restoreAccessToken', () => {
const user = EXAMPLE_USER;

beforeEach(async () => {
await authService.getAccessToken({ user });
});

it('getAccessToken should be called', () => {
expect(authService.getAccessToken).toBeCalled();
});
});
});
});
112 changes: 112 additions & 0 deletions src/apis/reviews/__test__/reviews.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { UnprocessableEntityException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { getRepositoryToken } from '@nestjs/typeorm';
import { ShopsService } from 'src/apis/shops/shops.service';
import { Repository } from 'typeorm';
import { Review } from '../entities/review.entity';
import { ReviewsService } from '../reviews.service';

jest.mock('../reviews.service');
const EXAMPLE_REVIEW = {
id: 'EXAMPLE_REVIEW_ID',
contents: 'EXAMPLE_REVIEW_CONTENTS',
createdAt: new Date(),
star: 5,
reservation: { id: '33bcbf41-884b-46f2-96a2-f3947a1ca906' },
shop: { id: '500d75e0-0223-4046-be13-55887bfbf6f0' },
};

const MockReviewsRepository = () => ({
find: jest.fn((where, skip, take, order, relations) => {
EXAMPLE_REVIEW;
}),
findOne: jest.fn((where, relations) => {
EXAMPLE_REVIEW;
}),
save: jest.fn(({ contents, star, reservation, shop }) => {
EXAMPLE_REVIEW;
}),
});

type MockRepository<T = any> = Partial<Record<keyof Repository<T>, jest.Mock>>;

describe('ReviewsService', () => {
let reviewsService: ReviewsService;
let shopsService: ShopsService;
let mockReviewsRepository: MockRepository<Review>;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
ReviewsService,
{
provide: getRepositoryToken(Review),
useValue: MockReviewsRepository(),
},
{
provide: ShopsService,
useValue: {
findById: jest.fn(() => true),
},
},
],
}).compile();

reviewsService = module.get<ReviewsService>(ReviewsService);
mockReviewsRepository = module.get(getRepositoryToken(Review));
});

const reviewId = EXAMPLE_REVIEW.id;
const shopId = 'shopId';

describe('find', () => {
it('reviewsRepository의 findOne을 실행하고 값이 없으면 error 반환해야함', async () => {
try {
const result = await mockReviewsRepository.findOne({
where: { id: reviewId },
relations: ['shop', 'reservation'],
});
} catch (error) {
expect(error).toBeInstanceOf(UnprocessableEntityException);
expect(error.message).toEqual('아이디를 찾을 수 없습니다');
}
expect(mockReviewsRepository.findOne).toBeCalled();
});
});

describe('findByShopIdWithPage', () => {
it('', () => {
try {
shopsService.findById({ shopId });
} catch (error) {
expect(error).toBeInstanceOf(Error);
throw new UnprocessableEntityException('유효하지 않은 가게ID 입니다');
}
const page = 1;
const count = 12;
const result = mockReviewsRepository.find({
where: { shop: { id: shopId } },
skip: (page - 1) * count,
take: count,
order: {
createdAt: 'ASC',
},
relations: ['shop', 'reservation'],
});

expect(mockReviewsRepository.find).toBeCalled();
});
});

describe('create', () => {
it('', async () => {});
});

describe('averageStar', () => {
it('', async () => {});
});

describe('checkReviewAuth', () => {
it('', async () => {});
});
});
7 changes: 5 additions & 2 deletions src/apis/shopImages/__test__/shopImage.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ describe('shopImagesService', () => {
try {
await checkShop({ shopId });
} catch (error) {
expect(error).toThrow(UnprocessableEntityException);
throw new UnprocessableEntityException();
expect(error).toBeInstanceOf(UnprocessableEntityException);
}

const result = mockShopImagesRepository.find({
Expand All @@ -117,7 +118,8 @@ describe('shopImagesService', () => {
try {
await checkURL({ shopId });
} catch (error) {
expect(error).toThrow(ConflictException);
throw new ConflictException();
expect(error).toBeInstanceOf(ConflictException);
}

const result = mockShopImagesRepository.save({
Expand Down Expand Up @@ -163,6 +165,7 @@ describe('shopImagesService', () => {
try {
await checkImage({ shopId });
} catch (error) {
throw new UnprocessableEntityException('아이디를 찾을 수 없습니다');
expect(error).toThrow(UnprocessableEntityException);
}
const result = await mockShopImagesRepository.delete({
Expand Down