요청 모크와 스파이
WebdriverIO는 백엔드 설정이나 모의 서버를 설정할 필요 없이 프론트엔드 애플리케이션 테스트에 집중할 수 있도록 네트워크 응답을 수정하는 내장 지원 기능을 제공합니다. 테스트에서 REST API 요청과 같은 웹 리소스에 대한 사용자 지정 응답을 정의하고 동적으로 수정할 수 있습니다.
mock 명령을 사용하려면 Chrome DevTools 프로토콜에 대한 지원이 필요합니다. 이 지원은 Chromium 기반 브라우저에서 로컬로 테스트를 실행하거나, Selenium Grid v4 이상 또는 Chrome DevTools 프로토콜을 지원하는 클라우드 벤더(예: SauceLabs, BrowserStack, LambdaTest)를 통해 테스트를 실행할 때 제공됩니다. 필요한 기본 요소가 Webdriver Bidi에 구현되고 각 브라우저에 구현되면 완전한 크로스 브라우저 지원이 가능해집니다.
모크 생성하기
응답을 수정하기 전에 먼저 모크를 정의해야 합니다. 이 모크는 리소스 URL로 설명되며 요청 메서드 또는 헤더로 필터링할 수 있습니다. 리소스는 minimatch에 의한 글로브 표현식을 지원합니다:
// "/users/list"로 끝나는 모든 리소스를 모킹
const userListMock = await browser.mock('**/users/list')
// 또는 헤더나 상태 코드로 리소스를 필터링하여 모크를 지정할 수 있습니다.
// json 리소스에 대한 성공적인 요청만 모킹
const strictMock = await browser.mock('**', {
// 모든 json 응답 모킹
requestHeaders: { 'Content-Type': 'application/json' },
// 성공한 응답만
statusCode: 200
})
사용자 지정 응답 지정하기
모크를 정의한 후에는 사용자 지정 응답을 정의할 수 있습니다. 이러한 사용자 지정 응답은 JSON으로 응답할 객체, 사용자 지정 fixture로 응답할 로컬 파일, 또는 인터넷의 리소스로 응답을 대체하는 웹 리소스일 수 있습니다.
API 요청 모킹
JSON 응답을 예상하는 API 요청을 모킹하려면 모크 객체에서 respond를 호출하고 반환하려는 임의의 객체를 전달하면 됩니다:
const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/')
mock.respond([{
title: 'Injected (non) completed Todo',
order: null,
completed: false
}, {
title: 'Injected completed Todo',
order: null,
completed: true
}], {
headers: {
'Access-Control-Allow-Origin': '*'
},
fetchResponse: false
})
await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')
await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li').map(el => el.getText()))
// 출력: "[ 'Injected (non) completed Todo', 'Injected completed Todo' ]"
또한 다음과 같이 일부 모의 응답 매개변수를 전달하여 응답 헤더와 상태 코드를 수정할 수 있습니다:
mock.respond({ ... }, {
// 상태 코드 404로 응답
statusCode: 404,
// 응답 헤더에 다음 헤더 병합
headers: { 'x-custom-header': 'foobar' }
})
백엔드를 전혀 호출하지 않으려면 fetchResponse 플래그에 false를 전달할 수 있습니다.
mock.respond({ ... }, {
// 실제 백엔드를 호출하지 않음
fetchResponse: false
})
사용자 지정 응답을 fixture 파일에 저장하여 테스트에서 다음과 같이 가져오는 것이 좋습니다:
// JSON import assertions를 지원하려면 Node.js v16.14.0 이상이 필요합니다
import responseFixture from './__fixtures__/apiResponse.json' assert { type: 'json' }
mock.respond(responseFixture)
텍스트 리소스 모킹
JavaScript, CSS 파일 또는 기타 텍스트 기반 리소스와 같은 텍스트 리소스를 수정하려면 파일 경로를 전달하면 WebdriverIO가 원본 리소스를 교체합니다:
const scriptMock = await browser.mock('**/script.min.js')
scriptMock.respond('./tests/fixtures/script.js')
// 또는 사용자 지정 JS로 응답
scriptMock.respond('alert("I am a mocked resource")')
웹 리소스 리디렉션
원하는 응답이 이미 웹에 호스팅되어 있는 경우 웹 리소스를 다른 웹 리소스로 대체할 수도 있 습니다. 이는 개별 페이지 리소스뿐만 아니라 웹 페이지 자체에서도 작동합니다:
const pageMock = await browser.mock('https://google.com/')
await pageMock.respond('https://webdriver.io')
await browser.url('https://google.com')
console.log(await browser.getTitle()) // "WebdriverIO · Next-gen browser and mobile automation test framework for Node.js" 반환
동적 응답
모의 응답이 원본 리소스 응답에 따라 달라지는 경우, 원본 응답을 매개변수로 받아 반환 값에 기반하여 모크를 설정하는 함수를 전달하여 리소스를 동적으로 수정할 수 있습니다:
const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/', {
method: 'get'
})
mock.respond((req) => {
// todo 내용을 목록 번호로 대체
return req.body.map((item, i) => ({ ...item, title: i }))
})
await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')
await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li label').map((el) => el.getText()))
// 반환:
// [
// '0', '1', '2', '19', '20',
// '21', '3', '4', '5', '6',
// '7', '8', '9', '10', '11',
// '12', '13', '14', '15', '16',
// '17', '18', '22'
// ]