글 작성자: 망고좋아
반응형

🎯 Async assertion

  • callback 패턴의 경우 test() 함수가 제공하는 done() 함수를 활용하여 콜백이 끝나고 done()을 호출이 된다. 에러가 발생하면 done()의 인자로 에러를 넘긴다.
  • Promise 패턴의 경우 async/await을 활용하거나 Promise를 리턴한다.
function isPythagoreanAsync(a, b, c) {
    return new Promise(resolve => {
        setTimeout(() => {
            const result = isPythagorean(a, b, c)
            if (result) return resolve(result)
            reject(new Error("Not pythagorean"))
        }, 500)
    })
}
test('Should 3, 4, 5 be pythagorean async', (done) => {
    isPythagoreanAsync(3, 4, 5).then(done).catch(done)
})

test('Should 3, 4, 5 be pythagorean async', () => {
    return expect(isPythagoreanAsync(3, 4, 5)).resolves.toBe(true)
})

test('Should 3, 4, 6 be not pythagorean async', () => {
    return expect(isPythagoreanAsync(3, 4, 6)).rejects.toBe("Not pythagorean")
})

 

📝 Mock functions

  • jest.fn()을 활용하여 mock function 객체를 만들 수 있다.
  • mockReturnValueOnce() 등으로 리턴하는 값을 임의로 조작할 수 있다. 여러 번 호출하면 순서대로 세팅된 값을 반환한다.
  • mockResolvedValue()로 promise가 resolve 하는 값을 조작할 수 있다.
  • jest.mock()으로 특정 모듈을 mocking 한다.

 

  • 실제로 비동기 작업 테스트는 서버에 http 요청을 보내지 않는다.
    • 서버 과부하
    • post 요청 경우 실제로 db에 들어가서 변경될 수 있어서
    • 따라서 fetch가 성공적으로 요청하는지는 테스트하면 안 된다.
  • 요청에 대한 데이터를 받았을 때 컴포넌트가 올바르게 동작하는지 테스트해 줘야 한다.
  • 그래서 fetch를 mock 함수로 대체해야 한다.
import { render, screen } from "@testing-library/react";
import Async from "./Async";

describe("비동기 컴포넌트", () => {
  test("renders posts if request succeeds", async () => {
    window.fetch = jest.fn(); // 내장 fetch 함수를 mock 함수로 덮어쓰기
    window.fetch.mockResolvedValueOnce({
      json: async () => [{ id: "p1", title: "첫 포스트!" }], // fetch를 하면 json이 반환되고 then을 해서 date를 받기 때문에 동일한 시나리오로 작성
    }); // fetch가 호출될 때 resolved 되면 지정한 값을 반환

    render(<Async />);

    const listItemElements = await screen.findAllByRole("listitem");
    // 한 개 이상의 item을 가져오니까 findAllByRole 사용
    // find는 원하는 원소가 없더라도 비동기적으로 기다리게 된다.
    expect(listItemElements).not.toHaveLength(0); //성공하면 빈 배열을 가져오지 않으니까 not.toHaveLength(0)를 통해서 빈 배열이 아닌지 test
  });
});
  • jest.fn();는 mock 함수를 만든다.
  • mockResolvedValueOnce는 (한 번만) 비동기 모의 함수가 이행(Resolved) 되면 지정한 값을 반환한다.

 

📕 Mock functions - assertion

  • toHaveBeenCalled : 이 함수가 호출되었는지 검증
  • toHaveBeenCalledWith(arg1, arg2, ...) : 이 함수가 특정 인자와 함께 호출되었는지 검증
  • toHaveBeenLastCalledWith(arg1, arg2, ...) : 마지막으로 특정 인자와 함께 호출되었는지 검증

 

📝 Lifecycle functions

  • beforeEach
  • afterEach
  • beforeAll
  • afterAll
beforeEach(() => {
    setupMockData()
})

afterEach(() => {
    clearMockData()
})

 

📝 Grouping

  • describe()
  • test()
describe('This is group 1', () => {
    describe('This is inner group 1', () => {
        test('Test 1', () => {})
    })

    describe('This is inner group 2', () => {
        test('Test 2', () => {})
    })
})

 

📝 Snapshot testing

  • toMatchSnapshot()을 호출하면, 기존에 스냅샷이 없었을 경우 .snap 파일을 만든다.
  • 기존 스냅샷이 있을 경우, 새로운 스냅샷과 비교하여 변경 사항이 있으면 테스트는 실패한다.
  • toMatchInlineSnapshot() 을 호출하면 별도의 스냅샷 파일을 만들지 않는다. 이 경우, 어떻게 스냅샷이 쓰였는지를 하나의 파일 안에서 알 수 있게 된다.
    • 코드의 길이가 길어질 수 있다. 선호도에 따라서 별도의 파일을 만들거나 하나의 파일에 만들지 결정할 수 있다.
import { render } from "@testing-library/react";

test('Snapshot test form', () => {
    const { container } = render(<MyForm />)
    expect(container.firstChild).toMatchSnapshot() // 별도의 파일을 만든다.
})

test('Snapshot test form', () => {
    const { container } = render(<MyForm />)
    expect(container.firstChild).toMatchInlineSnapshot()
})

 

📝 Snapshot testing

expect(container.firstChild).toMatchInlineS
napshot(`
    <div>
        <div>
            <img
                alt="Placeholder"
                src="<https://via.placeholder.com/150>"
            />
        </div>
    <form
        id="programming-form"
    >
    <fieldset>
        <legend>
            Basic Info
        </legend>
        <label
            for="username"
        >
        Username
        </label>
        ...
 
반응형