메모 조회에 대한 필수 값 누락에 대한 테스트 진행
단건 조회
const { readMemo } = require("../../src/memo/readMemo");
describe("readMemo", () => {
test("정상 id이면 memo 단건 조회에 성공한다", async () => {
const result = await readMemo(1);
expect(result).toMatchObject({
id: 1,
title: "TDD 메모 작성",
period: {
startDate: "2026-03-06",
endDate: "2026-03-10",
},
content: "첫 번째 메모",
priority: 3,
isSuccess: false,
});
});
test("id가 없으면 에러 발생", async () => {
await expect(readMemo()).rejects.toThrow("id");
});
test("id가 null이면 에러 발생", async () => {
await expect(readMemo(null)).rejects.toThrow("id");
});
test("id가 문자열이면 에러 발생", async () => {
await expect(readMemo("1")).rejects.toThrow("id");
});
test("id가 0이면 에러 발생", async () => {
await expect(readMemo(0)).rejects.toThrow("id");
});
test("id가 음수이면 에러 발생", async () => {
await expect(readMemo(-1)).rejects.toThrow("id");
});
test("존재하지 않는 id이면 에러 발생", async () => {
await expect(readMemo(999)).rejects.toThrow("memo");
});
});
실행 로그
hongseongchae@hongseongchaeui-MacBookPro tdd_study % npm test
> tdd_study@1.0.0 test
> jest
FAIL __test__/memo/readMemo.test.js
● readMemo › 정상 id이면 memo 단건 조회에 성공한다
TypeError: readMemo is not a function
3 | describe("readMemo", () => {
4 | test("정상 id이면 memo 단건 조회에 성공한다", async () => {
> 5 | const result = await readMemo(1);
| ^
6 |
7 | expect(result).toMatchObject({
8 | id: 1,
at Object.readMemo (__test__/memo/readMemo.test.js:5:26)
● readMemo › id가 없으면 에러 발생
TypeError: readMemo is not a function
19 |
20 | test("id가 없으면 에러 발생", async () => {
> 21 | await expect(readMemo()).rejects.toThrow("id");
| ^
22 | });
23 |
24 | test("id가 null이면 에러 발생", async () => {
at Object.readMemo (__test__/memo/readMemo.test.js:21:18)
● readMemo › id가 null이면 에러 발생
TypeError: readMemo is not a function
23 |
24 | test("id가 null이면 에러 발생", async () => {
> 25 | await expect(readMemo(null)).rejects.toThrow("id");
| ^
26 | });
27 |
28 | test("id가 문자열이면 에러 발생", async () => {
at Object.readMemo (__test__/memo/readMemo.test.js:25:18)
● readMemo › id가 문자열이면 에러 발생
TypeError: readMemo is not a function
27 |
28 | test("id가 문자열이면 에러 발생", async () => {
> 29 | await expect(readMemo("1")).rejects.toThrow("id");
| ^
30 | });
31 |
32 | test("id가 0이면 에러 발생", async () => {
at Object.readMemo (__test__/memo/readMemo.test.js:29:18)
● readMemo › id가 0이면 에러 발생
TypeError: readMemo is not a function
31 |
32 | test("id가 0이면 에러 발생", async () => {
> 33 | await expect(readMemo(0)).rejects.toThrow("id");
| ^
34 | });
35 |
36 | test("id가 음수이면 에러 발생", async () => {
at Object.readMemo (__test__/memo/readMemo.test.js:33:18)
● readMemo › id가 음수이면 에러 발생
TypeError: readMemo is not a function
35 |
36 | test("id가 음수이면 에러 발생", async () => {
> 37 | await expect(readMemo(-1)).rejects.toThrow("id");
| ^
38 | });
39 |
40 | test("존재하지 않는 id이면 에러 발생", async () => {
at Object.readMemo (__test__/memo/readMemo.test.js:37:18)
● readMemo › 존재하지 않는 id이면 에러 발생
TypeError: readMemo is not a function
39 |
40 | test("존재하지 않는 id이면 에러 발생", async () => {
> 41 | await expect(readMemo(999)).rejects.toThrow("memo");
| ^
42 | });
43 | });
44 |
at Object.readMemo (__test__/memo/readMemo.test.js:41:18)
PASS __test__/memo/createMemo.test.js
Test Suites: 1 failed, 1 passed, 2 total
Tests: 7 failed, 16 passed, 23 total
Snapshots: 0 total
Time: 0.498 s, estimated 1 s
Ran all test suites.
리스트 조회
const { listMemo } = require("../../src/memo/readMemo");
describe("listMemo", () => {
test("page와 pageSize가 정상 입력이면 memo 목록 조회에 성공한다", async () => {
const result = await listMemo({
page: 1,
pageSize: 10,
});
expect(Array.isArray(result)).toBe(true);
});
test("page가 없으면 에러 발생", async () => {
await expect(
listMemo({
pageSize: 10,
}),
).rejects.toThrow("page");
});
test("pageSize가 없으면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
}),
).rejects.toThrow("pageSize");
});
test("page가 숫자가 아니면 에러 발생", async () => {
await expect(
listMemo({
page: "1",
pageSize: 10,
}),
).rejects.toThrow("page");
});
test("pageSize가 숫자가 아니면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
pageSize: "10",
}),
).rejects.toThrow("pageSize");
});
test("page가 1보다 작으면 에러 발생", async () => {
await expect(
listMemo({
page: 0,
pageSize: 10,
}),
).rejects.toThrow("page");
});
test("pageSize가 1보다 작으면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
pageSize: 0,
}),
).rejects.toThrow("pageSize");
});
test("isSuccess가 boolean이 아니면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
pageSize: 10,
isSuccess: "true",
}),
).rejects.toThrow("isSuccess");
});
test("isSuccess가 true이면 성공한 메모만 조회", async () => {
const result = await listMemo({
page: 1,
pageSize: 10,
isSuccess: true,
});
expect(Array.isArray(result)).toBe(true);
result.forEach((memo) => {
expect(memo.isSuccess).toBe(true);
});
});
test("isSuccess가 false이면 진행 중 메모만 조회", async () => {
const result = await listMemo({
page: 1,
pageSize: 10,
isSuccess: false,
});
expect(Array.isArray(result)).toBe(true);
result.forEach((memo) => {
expect(memo.isSuccess).toBe(false);
});
});
test("priority가 숫자가 아니면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
pageSize: 10,
priority: "3",
}),
).rejects.toThrow("priority");
});
test("priority가 1보다 작으면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
pageSize: 10,
priority: 0,
}),
).rejects.toThrow("priority");
});
test("priority가 5보다 크면 에러 발생", async () => {
await expect(
listMemo({
page: 1,
pageSize: 10,
priority: 6,
}),
).rejects.toThrow("priority");
});
test("priority가 주어지면 해당 priority 메모만 조회", async () => {
const result = await listMemo({
page: 1,
pageSize: 10,
priority: 3,
});
expect(Array.isArray(result)).toBe(true);
result.forEach((memo) => {
expect(memo.priority).toBe(3);
});
});
});
실행 로그
hongseongchae@hongseongchaeui-MacBookPro tdd_study % npm test
> tdd_study@1.0.0 test
> jest
PASS __test__/memo/createMemo.test.js
PASS __test__/memo/readMemo.test.js
FAIL __test__/memo/readMemoList.test.js
● listMemo › page와 pageSize가 정상 입력이면 memo 목록 조회에 성공한다
TypeError: listMemo is not a function
3 | describe("listMemo", () => {
4 | test("page와 pageSize가 정상 입력이면 memo 목록 조회에 성공한다", async () => {
> 5 | const result = await listMemo({
| ^
6 | page: 1,
7 | pageSize: 10,
8 | });
at Object.listMemo (__test__/memo/readMemoList.test.js:5:26)
● listMemo › page가 없으면 에러 발생
TypeError: listMemo is not a function
13 | test("page가 없으면 에러 발생", async () => {
14 | await expect(
> 15 | listMemo({
| ^
16 | pageSize: 10,
17 | }),
18 | ).rejects.toThrow("page");
at Object.listMemo (__test__/memo/readMemoList.test.js:15:7)
● listMemo › pageSize가 없으면 에러 발생
TypeError: listMemo is not a function
21 | test("pageSize가 없으면 에러 발생", async () => {
22 | await expect(
> 23 | listMemo({
| ^
24 | page: 1,
25 | }),
26 | ).rejects.toThrow("pageSize");
at Object.listMemo (__test__/memo/readMemoList.test.js:23:7)
● listMemo › page가 숫자가 아니면 에러 발생
TypeError: listMemo is not a function
29 | test("page가 숫자가 아니면 에러 발생", async () => {
30 | await expect(
> 31 | listMemo({
| ^
32 | page: "1",
33 | pageSize: 10,
34 | }),
at Object.listMemo (__test__/memo/readMemoList.test.js:31:7)
● listMemo › pageSize가 숫자가 아니면 에러 발생
TypeError: listMemo is not a function
38 | test("pageSize가 숫자가 아니면 에러 발생", async () => {
39 | await expect(
> 40 | listMemo({
| ^
41 | page: 1,
42 | pageSize: "10",
43 | }),
at Object.listMemo (__test__/memo/readMemoList.test.js:40:7)
● listMemo › page가 1보다 작으면 에러 발생
TypeError: listMemo is not a function
47 | test("page가 1보다 작으면 에러 발생", async () => {
48 | await expect(
> 49 | listMemo({
| ^
50 | page: 0,
51 | pageSize: 10,
52 | }),
at Object.listMemo (__test__/memo/readMemoList.test.js:49:7)
● listMemo › pageSize가 1보다 작으면 에러 발생
TypeError: listMemo is not a function
56 | test("pageSize가 1보다 작으면 에러 발생", async () => {
57 | await expect(
> 58 | listMemo({
| ^
59 | page: 1,
60 | pageSize: 0,
61 | }),
at Object.listMemo (__test__/memo/readMemoList.test.js:58:7)
● listMemo › isSuccess가 boolean이 아니면 에러 발생
TypeError: listMemo is not a function
65 | test("isSuccess가 boolean이 아니면 에러 발생", async () => {
66 | await expect(
> 67 | listMemo({
| ^
68 | page: 1,
69 | pageSize: 10,
70 | isSuccess: "true",
at Object.listMemo (__test__/memo/readMemoList.test.js:67:7)
● listMemo › isSuccess가 true이면 성공한 메모만 조회
TypeError: listMemo is not a function
74 |
75 | test("isSuccess가 true이면 성공한 메모만 조회", async () => {
> 76 | const result = await listMemo({
| ^
77 | page: 1,
78 | pageSize: 10,
79 | isSuccess: true,
at Object.listMemo (__test__/memo/readMemoList.test.js:76:26)
● listMemo › isSuccess가 false이면 진행 중 메모만 조회
TypeError: listMemo is not a function
87 |
88 | test("isSuccess가 false이면 진행 중 메모만 조회", async () => {
> 89 | const result = await listMemo({
| ^
90 | page: 1,
91 | pageSize: 10,
92 | isSuccess: false,
at Object.listMemo (__test__/memo/readMemoList.test.js:89:26)
● listMemo › priority가 숫자가 아니면 에러 발생
TypeError: listMemo is not a function
101 | test("priority가 숫자가 아니면 에러 발생", async () => {
102 | await expect(
> 103 | listMemo({
| ^
104 | page: 1,
105 | pageSize: 10,
106 | priority: "3",
at Object.listMemo (__test__/memo/readMemoList.test.js:103:7)
● listMemo › priority가 1보다 작으면 에러 발생
TypeError: listMemo is not a function
111 | test("priority가 1보다 작으면 에러 발생", async () => {
112 | await expect(
> 113 | listMemo({
| ^
114 | page: 1,
115 | pageSize: 10,
116 | priority: 0,
at Object.listMemo (__test__/memo/readMemoList.test.js:113:7)
● listMemo › priority가 5보다 크면 에러 발생
TypeError: listMemo is not a function
121 | test("priority가 5보다 크면 에러 발생", async () => {
122 | await expect(
> 123 | listMemo({
| ^
124 | page: 1,
125 | pageSize: 10,
126 | priority: 6,
at Object.listMemo (__test__/memo/readMemoList.test.js:123:7)
● listMemo › priority가 주어지면 해당 priority 메모만 조회
TypeError: listMemo is not a function
130 |
131 | test("priority가 주어지면 해당 priority 메모만 조회", async () => {
> 132 | const result = await listMemo({
| ^
133 | page: 1,
134 | pageSize: 10,
135 | priority: 3,
at Object.listMemo (__test__/memo/readMemoList.test.js:132:26)
Test Suites: 1 failed, 2 passed, 3 total
Tests: 14 failed, 23 passed, 37 total
Snapshots: 0 total
Time: 0.488 s, estimated 1 s
Ran all test suites.
단건 조회
코드
async function readMemo(id) {
if (typeof id !== "number" || id <= 0) {
throw new Error("id");
}
const mockMemos = [
{
id: 1,
title: "TDD 메모 작성",
period: {
startDate: "2026-03-06",
endDate: "2026-03-10",
},
content: "조회 테스트용 메모",
priority: 3,
isSuccess: false,
},
{
id: 2,
title: "두 번째 메모",
period: {
startDate: "2026-03-07",
endDate: "2026-03-12",
},
content: "두 번째 조회 테스트용 메모",
priority: 2,
isSuccess: false,
},
];
const memo = mockMemos.find((item) => item.id === id);
if (!memo) {
throw new Error("memo");
}
return memo;
}
module.exports = { readMemo };
리스트 조회
코드
async function readMemo(id) {
if (typeof id !== "number" || id <= 0) {
throw new Error("id");
}
const mockMemos = [
{
id: 1,
title: "TDD 메모 작성",
period: {
startDate: "2026-03-06",
endDate: "2026-03-10",
},
content: "조회 테스트용 메모",
priority: 3,
isSuccess: false,
},
{
id: 2,
title: "두 번째 메모",
period: {
startDate: "2026-03-07",
endDate: "2026-03-12",
},
content: "두 번째 조회 테스트용 메모",
priority: 2,
isSuccess: false,
},
];
const memo = mockMemos.find((item) => item.id === id);
if (!memo) {
throw new Error("memo");
}
return memo;
}
async function listMemo(query) {
const { page, pageSize, isSuccess, priority } = query;
if (typeof page !== "number" || page < 1) {
throw new Error("page");
}
if (typeof pageSize !== "number" || pageSize < 1) {
throw new Error("pageSize");
}
if (isSuccess !== undefined && typeof isSuccess !== "boolean") {
throw new Error("isSuccess");
}
if (priority !== undefined) {
if (typeof priority !== "number" || priority < 1 || priority > 5) {
throw new Error("priority");
}
}
const mockMemos = [
{
id: 1,
title: "TDD 메모 작성",
period: {
startDate: "2026-03-06",
endDate: "2026-03-10",
},
content: "첫 번째 메모",
priority: 3,
isSuccess: false,
},
{
id: 2,
title: "두 번째 메모",
period: {
startDate: "2026-03-07",
endDate: "2026-03-12",
},
content: "두 번째 내용",
priority: 2,
isSuccess: true,
},
{
id: 3,
title: "세 번째 메모",
period: {
startDate: "2026-03-08",
endDate: "2026-03-15",
},
content: "세 번째 내용",
priority: 3,
isSuccess: true,
},
{
id: 4,
title: "네 번째 메모",
period: {
startDate: "2026-03-09",
endDate: "2026-03-18",
},
content: "네 번째 내용",
priority: 1,
isSuccess: false,
},
];
let result = mockMemos;
if (isSuccess !== undefined) {
result = result.filter((memo) => memo.isSuccess === isSuccess);
}
if (priority !== undefined) {
result = result.filter((memo) => memo.priority === priority);
}
const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize;
return result.slice(startIndex, endIndex);
}
module.exports = { readMemo, listMemo };
실행 로그
단건 조회
hongseongchae@hongseongchaeui-MacBookPro tdd_study % npm test
> tdd_study@1.0.0 test
> jest
PASS __test__/memo/readMemo.test.js
PASS __test__/memo/createMemo.test.js
Test Suites: 2 passed, 2 total
Tests: 23 passed, 23 total
Snapshots: 0 total
Time: 0.411 s, estimated 1 s
Ran all test suites.
리스트 조회
hongseongchae@hongseongchaeui-MacBookPro tdd_study % npm test
> tdd_study@1.0.0 test
> jest
PASS __test__/memo/readMemoList.test.js
PASS __test__/memo/createMemo.test.js
PASS __test__/memo/readMemo.test.js
Test Suites: 3 passed, 3 total
Tests: 37 passed, 37 total
Snapshots: 0 total
Time: 0.364 s, estimated 1 s
Ran all test suites.
코드
const mockMemos = [
{
id: 1,
title: "TDD 메모 작성",
period: {
startDate: "2026-03-06",
endDate: "2026-03-10",
},
content: "첫 번째 메모",
priority: 3,
isSuccess: false,
},
{
id: 2,
title: "두 번째 메모",
period: {
startDate: "2026-03-07",
endDate: "2026-03-12",
},
content: "두 번째 내용",
priority: 2,
isSuccess: true,
},
{
id: 3,
title: "세 번째 메모",
period: {
startDate: "2026-03-08",
endDate: "2026-03-15",
},
content: "세 번째 내용",
priority: 3,
isSuccess: true,
},
{
id: 4,
title: "네 번째 메모",
period: {
startDate: "2026-03-09",
endDate: "2026-03-18",
},
content: "네 번째 내용",
priority: 1,
isSuccess: false,
},
];
function validatePage(page) {
if (typeof page !== "number" || page < 1) {
throw new Error("page");
}
}
function validatePageSize(pageSize) {
if (typeof pageSize !== "number" || pageSize < 1) {
throw new Error("pageSize");
}
}
function validateIsSuccess(isSuccess) {
if (isSuccess !== undefined && typeof isSuccess !== "boolean") {
throw new Error("isSuccess");
}
}
function validatePriority(priority) {
if (priority !== undefined) {
if (typeof priority !== "number" || priority < 1 || priority > 5) {
throw new Error("priority");
}
}
}
function filterByIsSuccess(memos, isSuccess) {
if (isSuccess === undefined) {
return memos;
}
return memos.filter((memo) => memo.isSuccess === isSuccess);
}
function filterByPriority(memos, priority) {
if (priority === undefined) {
return memos;
}
return memos.filter((memo) => memo.priority === priority);
}
async function readMemo(id) {
if (typeof id !== "number" || id <= 0) {
throw new Error("id");
}
const memo = mockMemos.find((item) => item.id === id);
if (!memo) {
throw new Error("memo");
}
return memo;
}
async function listMemo(query) {
const { page, pageSize, isSuccess, priority } = query;
validatePage(page);
validatePageSize(pageSize);
validateIsSuccess(isSuccess);
validatePriority(priority);
let result = mockMemos;
result = filterByIsSuccess(result, isSuccess);
result = filterByPriority(result, priority);
const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize;
return result.slice(startIndex, endIndex);
}
module.exports = { readMemo, listMemo };
실행 로그
hongseongchae@hongseongchaeui-MacBookPro tdd_study % npm test
> tdd_study@1.0.0 test
> jest
PASS __test__/memo/readMemo.test.js
PASS __test__/memo/readMemoList.test.js
PASS __test__/memo/createMemo.test.js
Test Suites: 3 passed, 3 total
Tests: 37 passed, 37 total
Snapshots: 0 total
Time: 0.647 s, estimated 1 s
Ran all test suites.