API Mocking'i Mirage JS ve Vue.js ile Ayarlama
Yayınlanan: 2022-03-10SPA ve JAMstack çağında, API'ler ve ön uç geliştirme arasında her zaman bir endişe ayrılığı olmuştur. Vahşi doğada bulunabilen hemen hemen tüm JavaScript projeleri, bir web hizmeti veya API ile etkileşime girer ve onu kimlik doğrulama veya kullanıcıyla ilgili verileri almak için kullanır.
Bu nedenle, bir proje üzerinde çalıştığınız ve gerekli API'nin arka uç ekibi tarafından hala uygulanmadığı veya bir özelliği hızlı bir şekilde test etmeniz gerektiği zaman, aşağıdaki seçeneklerden bazılarına sahipsiniz:
- Çoğu durumda bir ön uç geliştirici olarak sahip olamayacağınız gerçek arka ucunuzun yerel olarak çalışan bir sürümüne proxy yapabilirsiniz.
- Gerçek isteği yorumlayabilir ve sahte verilerle değiştirebilirsiniz. (Bu sorun değil, ancak üretime geçmek için bunu geri almanız gerekeceğinden ve ağ durumları ve gecikmeyle başa çıkamayabilirsiniz kadar büyük değil.)
API Alaycılığı Nedir?
API alayı, gerçek bir API'nin taklidi veya simülasyonudur. Çoğunlukla, gerçek bir arka uç API'sine yapılması gereken istekleri engellemek için yapılır, ancak bu alay, ön uçunuzda bulunur.
API Alaycılığı Neden Önemlidir?
API alayı birçok yönden önemli ölçüde önemlidir:
- Özellikleri oluşturmadan önce üretim API'lerine bağımlı olmamak çok iyi bir ön uç geliştirme deneyimi sağlar.
- Tüm ön ucunuzu paylaşabilirsiniz ve gerçek bir arka uç API'sine bağlı olmadan çalışır.
Mirage JS Nedir?
Mirage JS, 5 yıl önce oluşturuldu ve Sam Selikoff, 24 Ocak 2020'de Twitter'da yayınlandığını resmi olarak duyurmadan önce Ember topluluğunda oldukça fazla kullanıldı.
Mirage JS, arka uç API'lerini bu API'lere bağımlı olmadan test etmek için sorunlu noktayı çözer. Üretim API'lerini taklit ederek sorunsuz ön uç geliştirme deneyimi sağlar.
Mirage JS, Vue.js, React, Angular ve Ember çerçeveleri için bir API alay kitaplığıdır
Mirage JS'yi Daha İyi Bir Seçim Yapan Nedir?
API alayı için başka seçenekler de var (Axios önleyicileri, Typicode'un JSON sunucusu vb. gibi) ancak Mirage hakkında oldukça ilginç olduğunu düşündüğüm şey, geliştirme sürecinizin önüne geçmemesi (göreceğiniz gibi) Vue ile biraz kurduğumuzda). Hafif ve aynı zamanda güçlüdür.
Zamanlama seçeneğiyle yavaş bir ağı simüle etmek gibi gerçek üretim API tüketim senaryolarını çoğaltmanıza olanak tanıyan kutudan çıkan pille birlikte gelir.
Mirage JS ve Vue.js'ye Başlarken
Artık Mirage JS'nin ne olduğunu ve ön uç geliştirme iş akışınız için neden önemli olduğunu bildiğinize göre, onu aşamalı web çerçevesiyle kurmaya bakalım: Vue.js.
Yeşil Alan (Temiz Kurulum) Vue Projesi Oluşturma
Vue CLI'yi kullanarak, projenin oluşturulmasını ve çalışmasını istediğiniz dizine giderek (terminalinizde) yeni bir Vue.js projesi oluşturun:
vue create miragejs-demo-vue
Yukarıdaki komut, şimdi cd
girebileceğiniz ve ya yarn serve
ya da npm run serve
yeni bir Vue projesi oluşturacaktır.
#Mirage JS'yi Yükleme
Şimdi aşağıdaki komutu çalıştırarak Vue.js projemizde bir geliştirme bağımlılığı olarak Mirage JS'yi kuralım:
yarn add -D miragejs
Veya NPM kullanıyorsanız, şunu çalıştırın:
npm install --save-dev miragejs
Ve bu kadar! Mirage JS artık Vue.js projemize yüklendi.
Hadi Bir Şeyle Alay Edelim
Mirage JS yüklendiğinde, onu Vue ile konuşacak ve temel bir yapılacaklar (bir yapılacaklar listesi döndüren bir API) API'si ile alay edecek şekilde nasıl yapılandırdığımızı görelim.
Sunucunuzu Tanımlayın
Başlamak için Vue.js projemizin /src
dizininde bir server.js dosyası oluşturmamız gerekiyor. Bundan sonra aşağıdakileri ekleyin:
import { Server, Model } from 'miragejs' export function makeServer({ environment = "development" } = {}) { let server = new Server({ environment, models: { todo: Model, }, seeds(server) { server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" }) }, routes() { this.namespace = "api" this.get("/todos", schema => { return schema.todos.all() }) }, }) return server }
Kod Açıklaması
İlk olarak, server.js dosyası, uygulamanızda tanımladığınız rotalarla eşleşen tüm API çağrılarını durduracak sahte (sahte) sunucusunun yeni bir örneğini oluşturmak için Mirage JS'yi nasıl kurduğunuzdur.
Şimdi, yukarıdakilerin ilk başta bunaltıcı olabileceğine katılıyorum, ancak burada neler olduğuna daha yakından bakalım:
import { Server, Model } from 'miragejs'
Yukarıdaki kod parçacığından, miragejs
Server
ve Model
içe aktarıyoruz.
-
Server
Bu, sahte sunucumuz olarak "hizmet etmek" için yeni bir Mirage JS sunucusu örneğini başlatmamıza yardımcı olmak için Mirage tarafından sunulan bir sınıftır. -
Model
Mirage'ın ORM'si tarafından desteklenen modeller (bir model, bir Mirage JS veritabanı girişinin yapısını belirler) oluşturmaya yardımcı olması için Mirage tarafından sunulan başka bir sınıf.
export function makeServer({ environment = "development" } = {}) {}
Yukarıdakiler temel olarak src/server.js
makeServer
adlı bir işlevi dışa aktarır. Ayrıca bir ortam parametresine geçtiğimizi ve Mirage'ın ortam modunu development
ayarladığımızı da not edebilirsiniz (bu makalenin ilerleyen kısımlarında test ortamından geçtiğimizi göreceksiniz).
makeServer
Şimdi makeServer
gövdesinde birkaç şey yapıyoruz. Hadi bir bakalım:
let server = new Server({})
Server sınıfının yeni bir örneğini başlatıyoruz ve ona bir yapılandırma seçeneği iletiyoruz. Yapılandırma seçeneklerinin içeriği, serap kurulumuna yardımcı olur:
{ environment, models: { todo: Model, }, seeds(server) { server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" }) }, routes() { this.namespace = "api" this.get("/todos", schema => { return schema.todos.all() }) }, }
İlk olarak fonksiyon tanımında başlattığımız environment
parametresini geçiyoruz.
models: { todo: Model, },
Bir sonraki seçenek olan models
seçeneği, Mirage'ın alay etmesini istediğimiz farklı modellerin bir nesnesini alır.
Yukarıda, Model sınıfından somutlaştırdığımız bir yapılacaklar modeli istiyoruz.
seeds(server) { server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" }) },
Sonraki seçenek, server
adlı bir parametreyi alan tohum yöntemidir. Tohum yöntemi, modellerimiz için tohumlar (tohumlar ilk veriler veya Mirage'ın veritabanına bir giriştir) oluşturmaya yardımcı olur. Bizim durumumuzda yapılacaklar modelinin tohumlarını oluşturmak için şunları yapıyoruz:
server.create("todo", { content: "Learn Mirage JS" }) server.create("todo", { content: "Integrate With Vue.js" })
bu nedenle sunucunun, ilk argüman olarak model adına karşılık gelen bir dize, ardından belirli bir tohumun özelliklerini veya niteliklerini içerecek bir nesneyi bekleyen bir create yöntemi vardır.
routes() { this.namespace = "api" this.get("/todos", schema => { return schema.todos.all() }) },
Son olarak, çeşitli rotaları tanımlayan rotalar yöntemimiz var (rotalar bizim sahte API uç noktalarımızdır) Mirage JS alay edecek. Yöntemin gövdesine bakalım:
this.namespace = "api"
bu satır, tüm rotalar için ad alanını ayarlar; bu, yapılacaklar rotamıza artık /api/todos'tan erişilebileceği anlamına gelir.
this.get("/todos", schema => { return schema.todos.all() })
Yukarıdakiler bir get yolu oluşturur ve bu, this.get()
yöntemini kullanarak işleyicisidir. get()
yöntemi, rotayı, yani “/todos”u ve schema
argüman olarak alan bir işleyici işlevini bekler. Şema nesnesi, Mirage JS bellek içi veritabanı tarafından desteklenen Mirage'ın ORM'si ile nasıl etkileşimde bulunduğunuzdur.
En sonunda:
return schema.todos.all()
Mirage'ın ORM'si tarafından mümkün kılınan şema nesnesini kullanarak tüm yapılacak işlerimizin bir listesini döndürüyoruz.
kaynak/main.js
Böylece src/server.js
kurulumunu bitirdik ama Vue bunu bilmiyor (en azından henüz değil). Şimdi bunu main.js dosyamıza şu şekilde aktaralım:
import { makeServer } from "./server"
Ardından makeServer
işlevini şöyle çağırırız:
if (process.env.NODE_ENV === "development") { makeServer() }
Yukarıdaki if
koşullu, serapın yalnızca geliştirme aşamasında çalıştığından emin olmak için bir korumadır.
Kurulum tamamlandı!
Şimdi Vue ile Miragejs kurduk. Eylemde görelim. App.vue dosyamızda içeriği siler ve aşağıdaki snippet ile değiştiririz:
<template> <ul> <li v-for="todo in todos" v-bind:key="todo.id">{{ todo.content }}</li> </ul> </template> <script> export default { name: 'app', data() { return { todos: [] } }, created() { fetch("/api/todos") .then(res => res.json()) .then(json => { this.todos = json.todos }) } } </script>
Vue.js'ye aşina iseniz, yukarıdakiler yeni bir şey olmaz, ancak toplam olması adına yaptığımız şey, App.vue
bileşenimiz oluşturulduğunda fetch
kullanarak bir API isteği yapmaktır, sonra döndürülen verileri iletiyoruz. bileşen durumumuzdaki todos dizisine. Daha sonra, yapılacaklar dizisini yinelemek için bir v-for kullanıyoruz ve her yapılacak işin content özelliğini görüntülüyoruz.
Mirage JS Bölümü Nerede?
Dikkat ederseniz, App.vue bileşenimizde Mirage'a özel bir şey yapmadık, normalde yaptığımız gibi sadece bir API çağrısı yapıyoruz. Mirage'ın bu özelliği, kaputun altındaki DX nedeni için gerçekten harika, Mirage, geliştirme aşamasındayken src/server.js'de tanımlanan yollardan herhangi biriyle eşleşen istekleri engeller.
Bu oldukça kullanışlıdır, çünkü rotaların üretim API uç noktalarınızla eşleşmesi koşuluyla, bir üretim ortamındayken gerçek bir üretim sunucusuna geçmek için sizin tarafınızdan herhangi bir çalışmaya ihtiyaç duyulmaz.
Bu nedenle, Mirage JS'yi test etmek için Vue dev sunucunuzu yarn serve
aracılığıyla yeniden başlatın.
İki todonun bir listesini görmelisiniz. Oldukça ilginç bulacağınız bir şey, Vue.js uygulamanızın bir parçası olarak çalışarak bu ek yükü ortadan kaldırdığı için Mirage'ı başlatmak için bir terminal komutu çalıştırmamıza gerek olmamasıdır.
Mirage JS ve Vue test araçları
Vue uygulamanızda zaten Vue Test-utils kullanıyorsanız, Mirage'ın ağ istekleriyle alay etmek için onunla kolayca çalışabileceğini bilmek heyecan verici olacaktır. Todos uygulamamızı kullanarak bir örnek kurulum görelim.
Birim testimiz için Jest kullanıyor olurduk. Dolayısıyla, takip ediyorsanız, @vue/unit-jest
eklentisini şu şekilde yüklemek için Vue CLI'yi hemen hemen kullanabilirsiniz:
vue add @vue/unit-jest
Yukarıdakiler @vue/cli-plugin-unit-jest
ve @vue/test-utils
geliştirme bağımlılıklarını kurarken aynı zamanda bir tests
dizini ve bir jest.config.js dosyası oluşturur. Ayrıca package.json scripts
bölümümüze aşağıdaki komutu ekleyecektir (oldukça temiz):
"test:unit": "vue-cli-service test:unit"
Test Edelim!
App.vue dosyamızı şöyle görünecek şekilde güncellerdik:
<!-- src/App.vue --> <template> <div v-if="serverError" data-test> {{ serverError }} </div> <div v-else-if="todos.length === 0" data-test> No todos! </div> <div v-else> <ul> <li v-for="todo in todos" v-bind:key="todo.id" :data-test > {{ todo.content }} </li> </ul> </div> </template> <script> export default { name: "app", data() { return { todos: [], serverError: null, } }, created() { fetch("/api/todos") .then(res => res.json()) .then(json => { if (json.error) { this.serverError = json.error } else { this.todos = json.todos } }) }, } </script>
Yukarıdaki snippet'te gerçekten epik bir şey olmuyor; sadece birim testimizle uygulayacağımız ağ testine izin verecek şekilde yapılanıyoruz.
Vue CLI zaten bizim için bir /tests
klasörü eklemiş olsa da, testlerim test ettikleri bileşenlerin yakınına yerleştirildiğinde bunu çok daha iyi bir deneyim olarak görüyorum. Bu nedenle, src/
içinde bir /__tests__
klasörü oluşturun ve bunun içinde bir App.spec.js dosyası oluşturun. (Bu aynı zamanda Jest tarafından önerilen yaklaşımdır.)
// src/__tests__/App.spec.js import { mount } from "@vue/test-utils" import { makeServer } from "../server" import App from "../App.vue" let server beforeEach(() => { server = makeServer({ environment: "test" }) }) afterEach(() => { server.shutdown() })
Birim testimizi kurmak için @vue/test-utils
adresinden mount
yöntemini, daha önce oluşturduğumuz Miragejs sunucusunu ve son olarak App.vue
bileşenini içe aktarıyoruz.
Ardından, test ortamından geçerken Mirage JS sunucusunu başlatmak için beforeEach
yaşam döngüsü işlevini kullanıyoruz. (Unutmayın, ortamı varsayılan olarak development
olarak ayarladık.)
Son olarak afterEach
server.shutdown
sunucuyu kapatıyoruz.
Testlerimiz
Şimdi testimizi detaylandıralım (Mirage js belgelerinin hızlı başlangıç bölümünü benimsiyor olacağız. Böylece, App.spec.js'niz sonunda şöyle görünecek:
// src/__tests__/App.spec.js import { mount } from "@vue/test-utils" import { makeServer } from "./server" import App from "./App.vue" let server beforeEach(() => { server = makeServer({ environment: "test" }) }) it("shows the todos from our server", async () => { server.create("todo", { id: 1, content: "Learn Mirage JS" }) server.create("todo", { id: 2, content: "Integrate with Vue.js" }) const wrapper = mount(App) // let's wait for our vue component to finish loading data // we know it's done when the data-testid enters the dom. await waitFor(wrapper, '[data-test]') await waitFor(wrapper, '[data-test]') expect(wrapper.find('[data-test]').text()).toBe("Learn Mirage JS") expect(wrapper.find('[data-test]').text()).toBe("Integrate with Vue.js") }) it("shows a message if there are no todo", async () => { // Don't create any todos const wrapper = mount(App) await waitFor(wrapper, '[data-test]') expect(wrapper.find('[data-test]').text()).toBe("No todos!") }) // This helper method returns a promise that resolves // once the selector enters the wrapper's dom. const waitFor = function(wrapper, selector) { return new Promise(resolve => { const timer = setInterval(() => { const todoEl = wrapper.findAll(selector) if (todoEl.length > 0) { clearInterval(timer) resolve() } }, 100) }) } afterEach(() => { server.shutdown() })
Not : Burada bir yardımcı kullanıyoruz (Mirage JS belgelerinde tanımlandığı gibi). Test ettiğimiz öğelerin DOM'da ne zaman olduğunu bilmemize izin veren bir söz verir.
Şimdi yarn test:unit
.
Tüm testleriniz bu noktada geçmelidir.
Mirage JS ile Farklı Sunucu Durumunu Test Etme
Farklı sunucu durumlarını test etmek için Mirage JS sunucumuzu değiştirebiliriz. Nasıl olduğunu görelim.
// src/__tests__/App.spec.js import { Response } from "miragejs"
İlk olarak, Mirage'dan Response
sınıfını içe aktarıyoruz, ardından aşağıdaki gibi yeni bir test senaryosu oluşturuyoruz:
it("handles error responses from the server", async () => { // Override Mirage's route handler for /todos, just for this test server.get("/todos", () => { return new Response( 500, {}, { error: "The database is taking a break.", } ) }) const wrapper = mount(App) await waitFor(wrapper, '[data-test]') expect(wrapper.find('[data-test]').text()).toBe( "The database is taking a break." ) })
Testinizi çalıştırın ve hepsi geçmelidir.
Çözüm
Bu makale, sizi Mirage JS ile tanıştırmayı ve bunun nasıl daha iyi bir ön uç geliştirme deneyimi sağladığını göstermeyi amaçladı. Mirage JS'nin ele almak için oluşturduğu sorunu (gerçek bir arka uç API'si olmadan üretime hazır ön uç oluşturma) ve bunun Vue.js ile nasıl kurulacağını gördük.
Bu makale Mirage JS'nin neler yapabileceğinin yüzeyini çizmesine rağmen, başlamanız için yeterli olduğuna inanıyorum.
- Belgeleri inceleyebilir ve Mirage JS discord sunucusuna katılabilirsiniz.
- Bu makalenin destekleyici deposu GitHub'da mevcuttur.
Referanslar
- Mirage Belgeleri
- Mirage Vue Hızlı Başlangıç