Node.js 심화주차 - jest 특강
1.테스트에 대한 고찰
- 사전에 알아야 할 배경 지식
- Node 심화 1주차 강의 완강 - 왜 테스트를 해야 하는가?
- Layered Architecture Pattern 고찰하기 - 계층 나누기 전
- Layered Architecture Pattern
오픈 소스 많이 보시면 보실수록 좋아요~
CI/CD 배포와 자동화~
Test code ..
- data mocking .. 뭘 mocking할 것인지 ..
- 코드 작성 논리적 흐름
- 검증하는 흐름
외부 의존성 ..
외부 라이브러리 호출 안 하는 쪽으로
테스트 코드를 작성하셔야 돼요.
Req, res는 어떤 라이브러리가 밀어주는 객체?
express가 넘겨준다 ..
Test code 작성할 때 express 끌어다 쓰면 안 된다.
테스트 코드는, 외부 라이브러리 자체에 대한 의존성이 없어야 한다.
테스트 코드는 테스트 코드만으로 돌아가야 한다.
테스트 코드 종류에 따라 달라질 수 있지만 ..
유닛 테스트에 대해서는 .. 외부 의존성 전혀 없는
코드 자체만으로 돌아가야 한다..
그래서 mocking 해야 한다..
Express 없이 쓸 수 있게 하게끔 …
Mock Data Setting .. Mocking ..
Before ForEach ~~
beforeEach
404를 주는지도 테스트 해야 한다
404를 주는 코드가 있기 때문에 ..
Fail cae 꼭 다루고 ..
Code coverage에서 내가 뭘 빼먹었는지 다 알려줘~
개발 관점에서 빨간 줄 없어지는 걸 목표로 잡아주면 되겠다 ..
Branches .. 분기 테스트 중요하다
TDD ..
테스트 코드 실패하도록 작성한다 ..
비즈니스 로직이 프레임워크와 떼놓을 수가 없다..
Presentation Layer - 컨롤롤러 Contool
- 컨트롤러(Controller)
- Service Layer (Service)
Api .. 전부 테스트하기 어렵다 ..
Layered Architecture Pattern에 대한 고찰 ..
Post 모델 만들었는데 find by … 어쩌구 .. 메서드 생성 ..
객체가 필요하고 어쩌구 .. 악순환의 반복 ..
메소드 계속 늘어나 ..
두 개 인스턴스 의존성이 생겨버려 ..
확장성에 있어서 어떤 단점 ..
무조건 나쁘다라는 게 아니다 ..
혼자 쓸 거면 Layered Architecture 안 나눠도 된다 ..
다 같이 협업 .. 더 나은 확장성 .. 미래를 위한 이야기 ..
덩어리 메서드 하나하나 접근하시는 게 좋다.
계층에 대한 논리적인 목적을 계속 생각해보시면서 ..
이건 validation이니까.. controller에 있으면 될 거 같아 ..
Req, res .. controller에서 사용 .. service에서는 사용하지 않는다.
Validation check, success case, failure case
계층 나누기 전에 불편했던 것 ..
~~ user .. method 만들고 .. parameter 추가하고 ..
repository부터 작성하면 좀 더 편할 수 있다.
repository가 의존성이 가장 적다
모델 자체의 crud에 집중해서 하면 되니..
Validation check .. parameter check ..
Parameter validation check ..
응집도는 떨어졌지만 관심사 분리는 확실히 됐다는 점!
Try Catch .. controller에만 있다 ..
If (!userId) {
throw new Error()
}
자바스크립트는 .. 에러 만나면 서비스 바로 멈추는데, try catch 있으면 에러 처리가 가능하다.
메서드 하나 분리해서 관심사 따라 하나하나 분리하다가 쭉 작성하면서 .. 편해지면 repository랑 .. 하나하나 쌓아 올라가시면 된다..
app.js .. 분리된 거 가져와서 ..
객체를 직접 new를 하고 있나요?
만들어진 것을 가져오고 있냐?
왜 직접 new를 안 하냐?
New : 해당 class 의존성 주입 ..
DI .. D
여기에서 new를 하는 순간 ..
서비스 로직이 조금이라도 바뀌는 순간 new가 잘 되는지 다시 테스트 해야 한다 ..
Service - Repository ..에서 api의 기능은 끝난 것과 다름이 없다.
여기서 요청을 밀어넣어주는 controller만이 있는 것이다..
계층 나눴을 때 테스트 코드 ..
계층 나누니 따로따로 테스트 할 수 있다 ..
합쳤을 때 post comment 말고 ..
나눴을 때 첫 번째 장점
현재 dbms를 사용하지 않았는데 dbms 사용하고 싶다면?
repository만 바꾸면 된다..
테스트 돌릴 때 DBMS 따로 돌릴 수 있고 ..
나눴을 때 두 번째 장점
프레임워크 자체를 바꿀 수 있다..
Service, repository만 있으면 api 명세, api 설계는 끝.
controller는 client의 요청 사항에 제한이 있다..
이것만 바꾸면 framework를 바꿀 수 있다.
Service, repository .. 외부 의존성이 전혀 없다 ..
어떤 걸 가져오든 ..
Koa
Layered architecture pattern ..
spring도 이렇게 나누어져 있다..
Nest.js도 .. layered architecture pattern ..
Layered architecture pattern과 테스트 코드는 따로이다.
테스트 자체와 레아패 .. 결합이 잘 맞고 궁합이 잘 맞아서 그렇지, 본질적으로는 분야가 다른 것이다.
관심사 분리 ..
무엇을 Mocking할까에 집중해야 한다.
“DBMS를 위한 라이브러리를 Mocking해야 한다.”
Prisma, type ORM …
mocking하는 것에 따라 test code가 달라지면 안 된다..
Test code 거의 유지가 되어야 한다 ..
테스트코드에서는 .. 무슨 메서드를 사용하든 ..
내가 작성한 코드 ..
Update 하려고 하는데 user를 못 찾는 경우?
toBeNull .. 일부러 오류를 발생 ..
Fail case 무조건 해주셔야 해요.
Service logic에서 mocking하는 주체? Repository ..
실제 repository를 가져와서 쓰진 않고 ..
repository를 mocking하는 것이다..
가짜 repository를 만드는 것 ..
이게 가능한 이유? 의존성 주입을 통한 의존성 분리를 해뒀기 때문에. DI를 해뒀기 때문에 .. new Repository를 했으면 의존성 주입을 못 했다.
mocking할 때 꼭 기억해야 하는 것 .. 가짜 함수 만드는 것 .. 실제로 호출되는 그런 메서드가 되는 게 아니라.. 테스트 제대로 하려면 .. 가짜여도 .. 실제 레포지토리의 메서드와 같아야 한다 ..
mockResolvedValue .. 이건 기억해주시면 좋다.
서비스 로직에서 ..
updateUser ..
repository의 메서드 2개 호출하고 있다 ..
이것에 대한 결과값을 .. 실제로 호출하는 게 아니라 ..
이 두 개 함수에 대한 결과값을 mocking 해두셔야 한다 ..
mockResolvedValue로 ..
이건 꼭 기억해주셔야 돼요.
서비스 로직 테스트하려면 repository 필요하니까 ..
이 결과를 mocking 해두셔야 한다 ..
이 메서드의 호출값을 꼭 mocking해주셔야 한다..
Null일 때 체크 잊지 않아주셔야 한다…
Describe 여러 개로 나누면 안 되나요? 왜 안 돼요? 돼요.
묶으시면 됩니다. 정답이 없습니다.
테스트 코드 커버리지. 어디까지 커버할 수 있는지가 핵심이다.
controller에서는 service가 mocking이 되어야 하는데,
controller는 역할이 client의 요청도 같이 받고 있다.
client의 요청을 흉내내줄 친구가 있으면 좋다.
client의 요청을 흉내내줄 친구를 mocking해두시는 게 좋다.
framework를 바꾸는 것 ..
Layered architecture pattern은
http 통신을 사용하지 않을 수도 있다.
controller 수정해서 소켓 통신을 사용할 수도 있다.
무엇을 mocking할 것인가? mocking하는 대상 ..
mocking하는 메서드 .. 실제 메서드와 같아야 ..
Service mocking할 때 .. returen value mocking하는 것 ..
Req res mocking하는 이유.. 실제 controller에서 요청 받아서 ..
Express framework가 밀어넣어주는 것 ..
Express의 res, req 객체 본따서 만드는 것 ..
Return value ..
mocking할 것은 .. user, service, request, response
응답 잘 주느냐? 요청 잘 받았냐? 여기에 집중이 되어 있다..
만들었니?의 관점이 아니다.
요청은 잘 받았니? 응답은 잘 줬니?
테스트 코드를 계속 바꿔가면서 보시는 게 좋다.
만들었니? 제대로 만들었니?
Controller ~ 응답 잘 받았니? 응답 잘 줬니?
테스트 코드가 layered의 특성을 따라간다..
에러 만들고 .. 404 .. 409 .. 500 ..
이걸 짰으면 .. 에러에 대한 테스트 코드도 꼭 작성해야 ..
Happy case보다 .. unhappy case ..
Fail case에 집중한 코드가 되어야 한다..
잘 줬니? 잘 받았니? 응답은 잘 주니?
delete할 때 .. update할 때 .. id .. 정보가 누락된 경우 ..
Fail case .. 잘 봐주시고 ..
Express, jest만 있으면 된다 ..
테스트하기 너무 쉬운 코드이다..
이해 잘 안 될 때에는 심플한 것부터 ..
테스트 코드와 계층 분리의 이야기 ..
——
튜터님 실패 케이스는 얼마나 딥하게 작성해야하나요 (예를 들어 인자를 3개를 받아야하는데 1/2/3 하나씩만 들어온 경우, 12/23/13 두개씩 들어온 경우, 셋 다 안 들어온 경우 이 7개의 실패 케이스에 대해서 다 작성을 해줘야 되는건가요..??)
——
다 테스트 하는 게 맞는데 .. 경우의 수가 너무 많다 .. 단순 validation은 library 꼭 써보셨으면 좋겠다.
현업이라 가정하면, validation 모든 경우의 수 잘 안 쓴다..
더 나아가서? 이런 걸 만들어주는 라이브러리가 또 따로 있다.
1번, 5번 값이 없을 때 .. 프레디 걸스?
JOI .. Validation 자체를 middleware에서 처리해주는 라이브러리 ..
Fakes
Javascript
——
router를 다 만들고 계층 분리를 하는 게 나을까요? 계층 분리로 시작하는 게 나을까요?
——
계층 분리를 먼저 시작하는 게 좋습니다
If (!email || !password .. )
Validation check ..
이 값 중에 하나만 없어도 어차피 터진다.
Validation 어떻게 하는지에 따라서 테스트 코드도 달라진다..
——
모든 경우의 수를 다 찾아내기 위해 테스트 코드를 작성하기 보다는 내가 예측한 경우의 수는 완벽하게 커버하는 지를 확인하기 위해 테스트 코드를 작성하는 거 같은데 이런 접근이 맞나여
—
맞는데 함정이 있다 그래서 탄생한 개발 방법론이 TDD ..
내가 쓴 것에 대한 테스트 코드를 쓰는 게 아니라 일단 테스트 코드부터 작성한다 ..
내가 쓴 코드가 정확하지 않을 수 있기 때문에 .. TDD 굉장히 어렵다 ..
테스트에 코드를 맞춘다~
——
근데 실질적으로 어차피 원코드가 변경되면 테스트 코드도 변경은 불가피 한거아닙니까??
—
레이어 분리를 잘 해뒀으면 .. 다른 레이어의 테스트 코드 변경은 필요하지 않다.. 계층 분리 해두었으니 ..
바꾸는 계층의 역할에 대해서만 테스트 해주면 된다 ~
영향 범위 확장해봐라 ~ 모듈이 100개야 ..
패턴이 나누어져 있는 것 vs 패턴이 안 나누어져 있는 것 ..
——
원코드 내부 로직이 바껴도 해당 코드의 리턴이 안바뀌면 테스트 코드를 변경할 필요가 없지 않나여
—
서비스 계층에서 내부 로직이 바뀌는 경우 테스트 코드 작성이 필요할 수도 있다. 필요하지 않을 수도 있고 .. 상황에 따라서 ..
—
베이직 특강 - 콜백함수 ..
디자인 패턴 .. 객체지향 .. 객체 관련 디자인 패턴 ..
빌더 패턴 ..
메서드 체이닝의 핵심 .. 자기 자신을 리턴한다.
——
json을 반환하고 메서드 체이닝이 안 일어나냐?
Json이 과연 무슨 object를 return하는지