我有一个处理API通信的服务(应该是唯一做实际API调用的文件)。我在我的商店里使用这个服务有一些问题。
我现在的逻辑是这样的:
为了交换服务以获得更好的可测试性,服务通过一个prop引入到Vue组件中。我的问题是,我找不到一个好的方法来告诉商店使用这个服务,所以我创建了一个可组合的useService
来"存储"服务,然后可以导入并在商店中使用。
// component.vue
const props = defineProps<{
service: ServiceInterface
}>()
// Get the composable and set the service
const actualService = useService()
actualService.setService(props.service)
// Use the store
const store = useStore()
// useService.ts
const service = ref<ServiceInterface>()
export const useService = () => {
const setService = (newService: ServiceInterface) => {
service.value = newService
}
return {
service,
setService
}
}
// useStore.ts
// import composable
const { service } = useService()
export const useStore = defineStore('storeName', {
actions: {
async fetchData(id: string) {
// Ensure service is set
if (!service.value) {
throw new Error('No service')
}
// Use service
service.value.getData(id)
}
}
})
这个设置确实有效,但是我需要仔细检查服务可用的每个方法,我觉得我把整个设置弄得过于复杂了。有人有什么想法来改进这个流程吗?
我想我正在寻找这样的东西(不工作):
export const useStore = (service: ServiceInterface) => {
return defineStore('storeName', {
actions: {
async fetchData(id: string) {
service.getData(id)
}
}
})
}
1条答案
按热度按时间jhdbpxl91#
我看不出有什么理由让服务成为React式的,你希望在测试中能够用模拟来替换它,但是一旦它被示例化了,你就不需要动态地替换它的任何方法(这是你希望它成为React式的唯一原因)
我会选择(
service.ts
):其他任何地方:
或者:
...args
替换为每次调用所需的实际参数。您可以在测试中轻松替换
service.ts
:或仅模拟特定方法:
@/path/to/service
是通用的。例如,如果你把service.ts
(或.js
)放在src/services
里面,路径实际上是@/services/service
。在一个测试套件中,通过使用jest.mock('@/services/service')
(或它的任何更具体的变体),你可以有效地用模拟替换那个模块的实际内容,同时运行那个测试套件中的测试。