안녕하세요.
제로초님 유닛테스트쪽 강의 듣고 프로젝트에 유닛테스트를 적용시켜보고 있는데요!
2가지에서 많이 막히고 있습니다.
데이터를 변수에 임시로 넣어주고 원하는 결과값 , 즉 toBe 쪽에 변수를 넣어주려고 하는 도중 계속 아래 오류가 발생하고 있습니다. 오류 메세지가 post 유형에는 없고.. hashtag 유형에 있다는 거면 제대로 작성한거 아닌가요..?
// 오류내용
Property 'post' is missing in type '{ id: number; postId: number; hashtag: string; createdAt: Date; }' but required in type 'Hashtag'.
post.entity.ts
import { PostType } from 'src/enum/postType.enum';
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
OneToMany,
} from 'typeorm';
import { Hashtag } from './hashtag.entity';
@Entity('posts')
export class Post {
@PrimaryGeneratedColumn()
id!: number;
@Column()
type!: PostType;
@Column()
title!: string;
... 생략
@CreateDateColumn({ name: 'created_at' })
createdAt!: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt!: Date;
@OneToMany(() => Hashtag, (hashtag) => hashtag.post)
hashtags: Hashtag[];
}
hashtag.entity.ts
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
ManyToOne,
JoinColumn,
} from 'typeorm';
import { Post } from './post.entity';
@Entity('hashtags')
export class Hashtag {
@PrimaryGeneratedColumn()
id!: number;
@Column({ name: 'post_id' })
postId: number;
@Column()
hashtag!: string;
@CreateDateColumn({ name: 'created_at' })
createdAt!: Date;
@ManyToOne(() => Post, (post) => post.hashtags)
@JoinColumn({ name: 'post_id' })
post: Post;
}
createQueryBuilder, leftJoinAndSelect, where, getOne 이거를 findOne 처럼 전부 만들어줘야 하는 것인가요..? 아래는 제가 서비스에서 사용했던 레포입니다! (테스트 파일 아닙니다!)
this.postRepository
.createQueryBuilder('posts')
.leftJoinAndSelect('posts.hashtags', 'hashtags')
.where('posts.id = :id', { id })
.getOne();
createQueryBuilder를 사용하는 강의가 없어서 검색중에 어떤 글을 발견하고 따라해봤지만 막혀서 질문 드립니다 ..! createQueryBuilder 이걸 사용하기 위해서는 어떤 방식으로 만들어야 하는건가요???
만약 아래처럼 만들었다고 해도 강의에서는 expect 안에 service.함수명 이런식으로 호출하시던데 만약 createQueryBuilder를 사용하게 되면 repository.createQueryBulder().leftAndJoin.... 이런식으로 똑같이 만들어주는건가요..?? 유닛테스트 작업이 처음이라 계속 막히는 것 같습니다...
const MockPostRepository = () => {
createQueryBuilder: jest.fn().mockReturnValue({
leftAndJoin: jest.fn().mockReturnThis(),
where: jest.fn().mockReturnThis(),
getOne: jest.fn().mockReturnThis(),
});
};
describe('PostService', () => {
let postService: PostService;
let postRepository: MockRepository<Post>;
beforeEach(async () => {
// 가짜 모듈 생성
const module = await Test.createTestingModule({
providers: [
PostService,
// 실제 디비가 아닌 목업 디비로 연결해서 사용하기 위함
{
provide: getRepositoryToken(Post),
useValue: MockPostRepository(),
},
],
}).compile();
// 가짜 모듈을 postService 변수에 담아줌
postService = module.get<PostService>(PostService);
postRepository = module.get<MockRepository<Post>>(getRepositoryToken(Post));
});
});
post가 필수네요. post?: 로 수정하세요.
네 그냥 똑같이 메서드 체이닝할 수 있게 만드시면 됩니다. 마지막에 getOne이나 getMany만 모킹값 리턴하면 됩니다.
답글
dev kim
2023.10.27빠른 답변 감사합니다!!
2번에 대해서 조금 더 여쭤보고 싶습니다. 3개가 실패했다고 오류뜨는데 이게 getOne, leftJoinAndSelect, where이 제대로 실행이 안되었다고 보는건가요..? post에 조인한 hashtag는 어떤식으로 가져와야 하는건가요..? MockPostRepository 안에 createQueryBuilder안에 전부 leftJoinAndSelect, where, getOne 은 들어가있습니다!
테스트 코드 작성한 내용
제로초(조현영)
2023.10.27getOne에서 expect한 값을 return해주셔야죠. getPostWithHashtagById가 엉뚱한 걸 return하고있잖아요.
dev kim
2023.10.27저 getOne에서 expect한 값을 리턴한다는게 잘 이해가 되지 않습니다..
제로초(조현영)
2023.10.27단적으로 말해서 getOne에서 postWithHashtagObject를 return하시면 됩니다.
dev kim
2023.10.27getOne 부분이 getOne: jest.fn().mockReturnThis() 이 부분을 말씀하시는게 맞나요..??
제로초(조현영)
2023.10.27네. getOne은 최종 결과물을 return해야지 왜 this를 return하나요
dev kim
2023.10.28아아.. 넵 빠른 답변 감사합니다!!