typescript - Χρήση έγχυσης εξαρτήσεων με vue/vitest


  1. Η Ρύθμισή Μου
  • Εφαρμογή Vue 3
  • Καταστήματα Pinia
  • Στο main.ts μου : app.use(myPlugin)
  • Στο MyPlugin.ts : Δημιουργώ και παρέχω υπό όρους ένα αποθετήριο (MyRepo) στην εφαρμογή με βάση ορισμένες περιβαλλοντικές συνθήκες. Αυτό το αποθετήριο μπορεί είτε να αλληλεπιδρά με ένα API είτε να παρέχει ψεύτικα δεδομένα για σκοπούς ανάπτυξης και δοκιμών.
  • Στο myStore.ts :
defineStore('myStore', () => {
  const repo = inject<MyRepoInterface>('myRepo');
  // ....
})
  1. Το πρόβλημά μου

Αντιμετωπίζω ένα πρόβλημα όταν γράφω τεστ που εξαρτώνται από ένα store το οποίο με τη σειρά του εξαρτάται από το myStore. Όταν καλείται η συνάρτηση inject μέσα στο τεστ μου, λαμβάνω την ακόλουθη προειδοποίηση: [Vue warn]: inject() μπορεί να χρησιμοποιηθεί μόνο μέσα στο setup() ή σε λειτουργικά components. Επιπλέον, το repo είναι undefined, με αποτέλεσμα να προκύπτουν σφάλματα.

  1. Η ερώτησή μου

Ψάχνω για μια λύση για να παρέχω το repository κατά τη διάρκεια της εγκατάστασης του πλαισίου δοκιμών μου (Vitest). Με αυτόν τον τρόπο, μπορώ να το εισάγω στον κώδικά μου τόσο κατά τη συνήθη εκτέλεση της εφαρμογής όσο και κατά την εκτέλεση των δοκιμών. Πώς μπορώ να το επιτύχω αυτό;


Κάθε κριτική για τον τρόπο που προσπαθώ να πετύχω Dependency Injection είναι ευπρόσδεκτη. Ευχαριστώ!

Απάντηση #1

Τα καταστήματα Pinia είναι μονάδες (singletons) που δημιουργούνται κατά την πρώτη κλήση της συνάρτησης store. Το ότι το inject χρησιμοποιείται στη συνάρτηση ρύθμισης του καταστήματος Pinia σημαίνει ότι η πρώτη χρήση θα πρέπει να είναι μέσα στη ρύθμιση του Vue component ή σε σύγχρονα hooks κύκλου ζωής, ενώ δεν υπάρχει τέτοιος περιορισμός για τα καταστήματα Pinia γενικά.

Θα ήταν επίσης αδύνατο να οριστεί ένα κατάστημα με αυτόν τον τρόπο χρησιμοποιώντας επιλογές καταστήματος αντί για συνάρτηση, ενώ γενικά είναι εναλλάξιμες.

Ένας πιο ευέλικτος και φιλικός προς τις δοκιμές τρόπος είναι να χρησιμοποιήσετε ρητή έγχυση εξαρτήσεων στη μέθοδο αποθήκευσης:

let repo = ref(null as unknown as MyRepoInterface);

let init = (cfg: { repo: MyRepoInterface }) => {
  repo.value = cfg.repo;
})

Και στο συστατικό App:

useMyStore().init({
  repo: inject<MyRepoInterface>('myRepo')
})