Написание кода при разработке через тестирование
Разработка через тестирование, также известная как TDD, - это подход к разработке программного обеспечения, при котором вы должны написать тест перед написанием любого функционального кода.
Обзор
Здесь у нас есть GET API:
url = "https://jsonplaceholder.typicode.com/photos"
Что возвращает массив объектов, как показано ниже:
[ { "albumId": 1, "id": 1, "title": "accusamus beatae ad facilis cum similique qui sunt", "url": "https://via.placeholder.com/600/92c952", "thumbnailUrl": "https://via.placeholder.com/150/92c952" }, { "albumId": 1, "id": 2, "title": "reprehenderit est deserunt velit ipsam", "url": "https://via.placeholder.com/600/771796", "thumbnailUrl": "https://via.placeholder.com/150/771796" } ]
Мы создадим класс диспетчера API, который внутренне использует Axios для реализации REST.
Нам нужно создать класс с именем ApiManager.js и соответствующий тестовый файл с именем ApiManager.test.js.
Написание базового теста и объекта класса
Давайте начнем с написания теста. Давайте предположим, что нашему классу ApiManager необходимо создать экземпляр с некоторым URL-адресом, а out apiManagerInstance имеет свойство с именем url, которое необходимо создать с помощью конструктора.
import ApiManager from "./ApiManager"; describe('ApiManager Construction test', () => { const mockURL = "https://mockurl.com"; // let instance = new ApiManager(mockURL); it("instance url property set properly",()=>{ expect(instance.url).toEqual(mockURL) }) })
Очевидно, что проверка завершится неудачно, потому что в ApiManager.js ничего нет.
Давайте напишем код для прохождения теста в ApiManager.js.
export default class ApiManager{ constructor(url){ this.url = url } }
Теперь наш тест пройден, и пришло время реорганизовать реальную реализацию. Вроде все нормально. Так что рефакторингу нечего.
Реализация метода GET с использованием разработки через тестирование
Теперь у нашего ApiManager будет метод getPhotos, который вернет из объекта массив фотографий с необходимыми данными. В нашем случае нам понадобится всего два поля из объекта {идентификатор альбома, url}
Сценарий будет как
- В ApiManager будет метод под названием getPhotos.
- getPhotos вызовет метод get axios с помощью instance.url.
- getPhotos вернет массив, содержащий {идентификатор альбома, url} из возвращенного массива объекта axios.get.
- getPhotos выдаст ошибку, если axios.get вернет ошибку
Настраивать
describe('getPhotos method Test', () => { const mockURL = "https://mockurl.com"; let instance = new ApiManager(mockURL); // Our Test cases will Goes Here !!!! }
Сценарий 1: у ApiManager будет метод getPhotos
it(“getPhotos method defined”,()=>{ expect(instance.getPhotos).toBeDefined(); })
Чтобы передать этот случай, напишите метод с именем getPhotos
getPhotos(){ }
Сейчас проходят испытания. 👌
Сценарий 2: getPhotos вызовет метод axios get с instance.url
it(“getPhotos will call axios.get method with instance.utl”,()=>{ jest.spyOn(Axios,”get”) // Axios get need to be spied by Jest instance.getPhotos(); // expect(Axios.get).toHaveBeenCalledWith(instance.url); })
Не получается правильно. Не беспокойтесь. Давай пройдем их
getPhotos(){ Axios.get(this.url) }
Теперь его снова прохождение ✔️.
Сценарий 3: getPhotos вернет массив из {id альбома, url}
it("getPhotos will return proper array of object for axios mock response",async ()=>{ const mockPhotos = [{ "albumId": 1, "id": 1, "title": "accusamus beatae ad facilis cum similique qui sunt", "url": "https://via.placeholder.com/600/92c952", "thumbnailUrl": "https://via.placeholder.com/150/92c952"}, { "albumId": 1, "id": 2, "title": "reprehenderit est deserunt velit ipsam", "url": "https://via.placeholder.com/600/771796", "thumbnailUrl": "https://via.placeholder.com/150/771796" }] const expectedResponse =[ { "albumId": 1, "url": "https://via.placeholder.com/600/92c952", }, { "albumId": 1, "url": "https://via.placeholder.com/600/771796", }] jest.spyOn(Axios,"get").mockResolvedValueOnce(mockPhotos); const response = await instance.getPhotos(); expect(response).toEqual(expectedResponse); })
Давайте передадим это
getPhotos(){ return new Promise((resolve,reject)=>{ Axios.get(this.url).then(response=>{ const filterArr = response.map(item=> { return { "albumId": item.albumId, "url": item.url } }) resolve(filterArr) }).catch(error=>{ }) }); }
Потрясающе, теперь все хорошо. Правильно? 🤘
Сценарий 4: getPhotos выдаст ошибку, если axios.get вернет ошибку
it("getPhotos will throw error if axios.get return error",async ()=>{ const mockError = { error:{ msg:"Something Wrong" } } jest.spyOn(Axios,"get").mockRejectedValueOnce(mockError); await instance.getPhotos().catch(error=>{ expect(error.error.msg).toEqual("Something Wrong") }); })
Давайте передадим это, добавив только одну строку, то есть reject (error) внутри блока catch.
getPhotos(){ return new Promise((resolve,reject)=>{ Axios.get(this.url).then(response=>{ const filterArr = response.map(item=> { return { "albumId": item.albumId, "url": item.url } }) resolve(filterArr) }).catch(error=>{ reject(error) // only add this }) }); }
Теперь все прошло правильно? ✔️
Престижность. У нас есть полная реализация HTTP GET с помощью разработки через тестирование. 👍🏻
Примечание. Не забудьте выполнить рефакторинг после прохождения тестов, если это необходимо.
Спасибо за прочтение! 🍻
JavaScript на простом английском языке
Понравилась эта статья? Если да, то получите больше похожего контента, подписавшись на наш канал YouTube!