promise sprint를 하던중 이슈가 생겼다.
const fs = require("fs");
const util = require("util");
const {
getBodyFromGetRequestPromise,
getDataFromFilePromise
} = require("../exercises/02_promiseConstructor");
const writeFilePromise = util.promisify(fs.writeFile);
const BASE_URL = "https://koreanjson.com/users/";
const fetchUsersAndWriteToFileAsync = async (readFilePath, writeFilePath) => {
const dataList = await getDataFromFilePromise(readFilePath);
const responseDataList = await Promise.all(
dataList.map(id => getBodyFromGetRequestPromise(BASE_URL + id))
);
const text = responseDataList.map(data => data.name).join("\n") + "\n";
writeFilePromise(writeFilePath, text); // < 이슈 부분 >
};
테스트케이스,
const fs = require("fs");
const { fetchUsersAndWriteToFileAsync } = require("../exercises/05_asyncAwait");
describe("Async & Await Test", () => {
describe("fetchUsersAndWriteToFileAsync", () => {
const readFilePath = "files/read/userId.txt";
const writeFilePath = "files/write/userName.txt";
beforeEach(() => {
fs.writeFileSync(writeFilePath, "");
});
// afterEach 라는 hook을 보면, ""으로 내용을 비우는 코드가 작성되어 있습니다.
afterEach(() => {
fs.writeFileSync(writeFilePath, "");
});
test("should return the promise created by the entire chain", () => {
const result = fetchUsersAndWriteToFileAsync(readFilePath, writeFilePath);
expect(result.constructor.name).toBe("Promise");
});
test("should eventually write a user name to a file", () => {
return fetchUsersAndWriteToFileAsync(readFilePath, writeFilePath).then(
() => {
const userNames = fs.readFileSync(writeFilePath, "utf8");
expect(userNames).toBe("이정도\n김재완\n김성은\n이주연\n구일모\n");
}
);
});
});
});
case1 ) writeFilePromise(writeFilePath, text)
case1 ) await writeFilePromise(writeFilePath, text)
궁금한부분 ) 왜 await를 붙여야 테스트가 통과하고 userName.txt
에 내용이 남지 않을까?
테스트를 잘 보면 그 이유를 알 수 있다..!!
beforeEach, afterEach는 jest에서 제공하는 도우미 기능이다.
beforeEach는 테스트가 실행되기 전에 초기화 시켜주는 기능을 한다.
beforeEach(() => {
fs.writeFileSync(writeFilePath, "");
});
afterEach는 테스트가 종료되고 상황을 정리해주는 기능을 한다. ( 테스트가 성공하지 않으면 실행되지 않는다 )
afterEach(() => {
fs.writeFileSync(writeFilePath, "");
});
위의 내용을 참고하여 아래의 코드를 보면,
return fetchUsersAndWriteToFileAsync(readFilePath, writeFilePath).then(
() => {
const userNames = fs.readFileSync(writeFilePath, "utf8");
expect(userNames).toBe("이정도\n김재완\n김성은\n이주연\n구일모\n");
}
);
테스트에서 fetchUsersAndWriteToFileAsync(readFilePath, writeFilePath)
를 실행시킨후 then
으로 파일내용을 읽어와 비교하고 있기때문에 fetchUsersAndWriteToFileAsync
함수에서 await
없이 writeFilePromise(writeFilePath, text)
를 실행해주면 비동기함수이기 때문에 함수가 실행이 끝날때까지 기다려주지 않아서 ''
과 비교하게 되고 await
를 사용해주면 함수 실행이 끝날때까지 기다려주기 때문에 파일을 다 읽어온후 비교해줘서 테스트가 정상적으로 통과되고 테스트가 통과되었으니 afterEach가 실행되어 userName.txt
가 ""
빈문자열로 저장되는 것이다.