typescript - Bruk avhengighetsinjeksjon med vue/vitest


  1. Min Oppsett
  • Vue 3-applikasjon
  • Pinia-butikker
  • I min main.ts : app.use(myPlugin)
  • I MyPlugin.ts: Jeg oppretter og tilbyr betinget et repository (MyRepo) til applikasjonen basert på noen miljøforhold. Dette repositoryet kan enten interagere med en API eller gi falske data for utvikling og testing.
  • I myStore.ts :
defineStore('myStore', () => {
  const repo = inject<MyRepoInterface>('myRepo');
  // ....
})
  1. Mitt problem

Jeg står overfor et problem når jeg skriver tester som avhenger av en store som selv avhenger av myStore. Når inject-funksjonen kalles innenfor testen min, får jeg følgende advarsel: [Vue warn]: inject() kan bare brukes inne i setup() eller funksjonelle komponenter. I tillegg er repo undefined, noe som resulterer i feil.

  1. Mitt spørsmål

Jeg leter etter en løsning for å kunne tilby repositoriet under oppsettet av testrammeverket mitt (Vitest). På denne måten kan jeg injisere det i koden min både under normal kjøring av applikasjonen og når jeg kjører tester. Hvordan kan jeg oppnå dette?


Enhver kritikk av måten jeg prøver å oppnå Dependency Injection på er velkommen. Takk!

Svar #1

Pinia-butikker er singletons som blir instantiert ved første kall av store-funksjonen. At inject brukes i Pinia-butikkenes setup-funksjon betyr at den første bruken bør være inne i Vue-komponentens setup eller samtidige livssyklushooks, mens det ikke er en slik begrensning for Pinia-butikker generelt.

Det ville også vært umulig å definere en butikk på denne måten med butikkalternativer i stedet for funksjon, selv om de vanligvis er utskiftbare.

En mer fleksibel og testvennlig måte er å bruke eksplisitt avhengighetsinjeksjon i lagringsmetoden:

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

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

Og i App-komponenten:

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