// package.json
"scripts": {
"test": "jest",
...prev
_ test _ dir 안에 있거나 name.test.js 와 같은 형식에 파일은 테스트파일로 인식한다
fn=> 간단 파라미터 두개 값 더하는 함수 import
test("설명 칸입니다", () => {
//설명
expect(1).toBe(1);
// expect 검증할 대상
// toBe에 기대되는 값 (반환 값)
});
test("3 + 3 =6", () => {
expect(fn.add(3, 3)).toBe(6);
});
test("3 + 3 !==7", () => {
expect(fn.add(3, 3)).not.toBe(7);
});
-> 설명칸을 통해서 오류 파악이 가능
-> tobe 부분에서 사용하는 함수를 "Macher" 라고 합니다
ex)
toEquals : 객체나 배열은 재귀적으로 돌기때문에 toBe가 아닌 toEquals사용
toBeTruthy() / toBeFalsy() : true면 테스트 통과 /false면 테스트 통과
toBeCalled() : 함수가 호출되었으면 통과
toHaveLength() : 배열의 길이를 체크하여 테스트 통과 여부
toContain() : 특정 원소가 배열에 들어있으면 통과
toBeNull : Null이면 통과
toBeGreaterThan : 초과
toBeGreaterThanEqual : 이상
toBeLessThan : 미만
toBeLessThanEqual : 이하
toThrow: 예외 발생 여부를 테스트
... 공식문서 참고
getName: (callback) => {
const name = "velog";
setTimeout(() => {
callback(name);
}, 3000);
},
...
//
test("3초후 받아온 이름은 velog", (done) => {
const callback = (name) => {
try {
expect(name).toBe("velog");
done();
} catch (e) {
done();
}
};
fn.getName(callback);
});
// done을사용하지 않을시 테스트에 오류가 나오지 않는다
// done이 호출되면 종료됩니다
// done사용 안할시 0.1ms가 걸림
getAge: () => {
const age = 30;
return new Promise((res, rej) => {
setTimeout(() => {
res(age);
}, 3000);
});
},
...
test("3초후 받아온 이름은 나이는 30", () => {
return fn.getAge().then((age) => {
expect(age).toBe(30);
});
});
test("3초후 받아온 나이는 30최소화", () => {
return expect(fn.getAge()).resolves.toBe(30);
});
//.rejects로는 에러를 반환
test("3초후 받아온 나이는 30 async await", async () => {
const age = await fn.getAge();
expect(age).toBe(30);
});
test("3초후 받아온 나이는 30최소화", async () => {
await expect(fn.getAge()).resolves.toBe(30);
});
let num = 0;
test("0 더하기 1은 1", () => {
num = fn.add(num, 1);
expect(num).toBe(1);
});
test("0 더하기 2은 2", () => {
num = fn.add(num, 2);
expect(num).toBe(2);
});
beforeEach(() => {
// 각 테스트 직전 실행
num = 0;
});
beforeEach: 테스트 직전 실행
afterEach: 테스트 직후 실행
beforeAll : 전체 테스트 직전 실행 (1번)
afterEachAll : 전체 테스트 직후 실행 (1번)
//비슷한 기능 묶음
describe("Car 관련 진업", () => {
let car;
beforeAll(async () => {
car = await fn.connectCarDb();
});
afterAll(async () => {
car = await fn.connectCarDb();
});
test("브랜드 BMW", () => {
expect(car.brand).toBe("BMW");
});
});
-> describe로 묶으면 해당 부분처럼 구분 지어서 확인가능
// only를 추가하여 한가지만 테스트를 진행ㄹ
test.only("0 + 3 =3", () => {
expect(fn.add(num, 3)).toBe(4);
});
// skip시 해당 테스트만 제외하고 진행이 가능
test.skip("0 + 3 =3", () => {
expect(fn.add(num, 3)).toBe(4);
});
const mockFn = jest.fn();
mockFn();
mockFn(1);
test("mock 테스트", () => {
console.log(mockFn.mock.calls);
expect("test").toBe("test");
});
const mockFn = jest.fn((num) => num + 1);
mockFn(10);
mockFn(20);
mockFn(30);
test("함수 호출은 3번", () => {
console.log(mockFn.mock.results);
expect(mockFn.mock.calls.length).toBe(3);
});
const mockFn = jest.fn();
mockFn
.mockReturnValueOnce(true)
.mockReturnValueOnce(false)
.mockReturnValueOnce(true)
.mockReturnValueOnce(false)
.mockReturnValue(true);
const results = [1, 2, 3, 4, 5].filter((num) => mockFn(num));
test("홀수 는 1,3,5", () => {
expect(results).toStrictEqual([1, 3, 5]);
});
createUser: (name) => {
console.log("실제로 사용자가 생성");
return {
name,
};
},
test("유저 생성", () => {
const user = fn.createUser("Mike");
expect(user.name).toBe("Mike");
});
jest.mock("./fn");
fn.createUser.mockReturnValue({ name: "Mike" });
Hello.js
const Hello = ({ user }) => {
return user?.name ? (
<div>
<h1>Hello! {user.name}</h1>
</div>
) : (
<button>로그인</button>
);
};
--------
Hello.test.js
test("Hello라는 글자가 포함되는가", () => {
render(<Hello user={user} />);
const helloEl = screen.getByText(/Hello/i);
expect(helloEl).toBeInTheDocument();
});
-> 문자에 Hello가 포함 여부 테스트
const user = {
name: "Mike",
age: 30,
};
const user2 = {
age: 30,
};
test("snapshot : name 있음", () => {
const el = render(<Hello user={user} />);
expect(el).toMatchSnapshot();
});
test("snapshot : name 없음", () => {
const el = render(<Hello user={user2} />);
expect(el).toMatchSnapshot();
});
-> 해당 부분이 변경이 되면 오류생김(이름 or 모든 부분)
-> u 를 클릭시 스냅샷 업데이트 (버그 잘 찾고 하셔야합니다)
test("초 표시", () => {
Date.now = jest.fn(() => 123456789);
const el = render(<Timer />);
expect(el).toMatchSnapshot();
});
-> 테스트는 항상 고정된 값으로 사용되므로 mock함수를 통해서 처리가 가능합니다~
수정이 자주 일어나는 화면 같은경우는 스냅샷 기능을 자제해야합니다