【问题标题】:How can I modify the value of state in pinia in vue3 component test and affect the component?vue3组件测试中如何修改pinia中state的值并影响组件?
【发布时间】:2022-10-05 20:49:15
【问题描述】:

使用vue-test-utils来测试使用pinia的组件,需要修改pinia中存储的state的值,但是尝试了很多方法都无济于事。原始组件和存储文件如下。

// HelloWorld.vue
<template>
    <h1>{{ title }}</h1>
</template>

<script>
import { useTestStore } from \"@/stores/test\";
import { mapState } from \"pinia\";

export default {
    name: \"HelloWorld\",
    
    computed: {
        ...mapState(useTestStore, [\"title\"]),
    },
};
</script>
// @/stores/test.js
import { defineStore } from \"pinia\";

export const useTestStore = defineStore(\"test\", {
    state: () => {
        return { title: \"hhhhh\" };
    },
});

已尝试以下方法。

  1. 将组件内使用的store导入到测试代码中直接进行修改,但修改不会影响组件。
    // test.spec.js
    import { mount } from \"@vue/test-utils\";
    import { createTestingPinia } from \"@pinia/testing\";
    import HelloWorld from \"@/components/HelloWorld.vue\";
    import { useTestStore } from \"@/stores/test\";
    
    test(\"pinia in component test\", () => {
     const wrapper = mount(HelloWorld, {
         global: {
             plugins: [createTestingPinia()],
         },
     });
     const store = useTestStore();
     store.title = \"xxxxx\";
    
     console.log(wrapper.text()) //\"hhhhh\";
    });
    
    1. 使用 initialState 试图覆盖原始存储的内容,但再次没有任何效果。
    // test.spec.js
    import { mount } from \"@vue/test-utils\";
    import { createTestingPinia } from \"@pinia/testing\";
    import HelloWorld from \"@/components/HelloWorld.vue\";
    
    test(\"pinia in component test\", () => {
     const wrapper = mount(HelloWorld, {
         global: {
             plugins: [createTestingPinia({ initialState: { title: \"xxxxx\" } })],
         },
     });
     console.log(wrapper.text()) //\"hhhhh\";
    });
    
    1. 修改测试代码中传递给 global.plugins 的 TestingPinia 对象,但再次没有效果。
    // test.spec.js
    import { mount } from \"@vue/test-utils\";
    import { createTestingPinia } from \"@pinia/testing\";
    import HelloWorld from \"@/components/HelloWorld.vue\";
    
    test(\"pinia in component test\", () => {
     const pinia = createTestingPinia();
     pinia.state.value.title = \"xxxxx\";
     const wrapper = mount(HelloWorld, {
         global: {
             plugins: [pinia],
         },
     });
     console.log(wrapper.text()) //\"hhhhh\";
    });
    
    1. 使用 global.mocks 来模拟组件中使用的状态,但这仅适用于组件中使用 setup() 传入的状态,而使用 mapState() 传入的状态无效。
    // test.spec.js
    import { mount } from \"@vue/test-utils\";
    import { createTestingPinia } from \"@pinia/testing\";
    import HelloWorld from \"@/components/HelloWorld.vue\";
    
    test(\"pinia in component test\", () => {
     const wrapper = mount(HelloWorld, {
         global: {
             plugins: [createTestingPinia()],
             mocks: { title: \"xxxxx\" },
         },
     });
     console.log(wrapper.text()) //\"hhhhh\"
    });
    

    标签: javascript vue.js jestjs vue-test-utils pinia


    【解决方案1】:

    这已使用jest.mock() 解决。

    import { mount } from "@vue/test-utils";
    import { createPinia } from "pinia";
    import HelloWorld from "@/components/HelloWorld.vue";
    
    jest.mock("@/stores/test", () => {
        const { defineStore } = require("pinia");
        const useTestStore = defineStore("test", { state: () => ({ title: "xxxxx" }) });
        return { useTestStore };
    });
    
    test("pinia in component test", () => {
        const wrapper = mount(HelloWorld, {
            global: { plugins: [createPinia()] },
        });
        expect(wrapper.text()).toBe("xxxxx");
    });
    

    【讨论】:

    • 这对我不起作用。由于某种原因,我得到了一个空状态。
    【解决方案2】:

    感谢 Red Panda 提供这个主题。我使用“testing-library”和“vue-testing-library”而不是“vue-test-utils”和“jest”,但问题是一样的 - 无法更改商店的 pinia 初始数据。 我终于找到了解决此问题的方法,而无需模拟该功能。 当你 $patch 数据时,你只需要等待为了它。不知何故,它有帮助。我的代码看起来像这样,它完全有效:

    Popup.test.js

    import { render, screen } from '@testing-library/vue'
    import { createTestingPinia } from '@pinia/testing'
    import { popup } from '@/store1/popup/index'
    import Popup from '../../components/Popup/index.vue'
    
    describe('Popup component', () => {
      test('displays popup with group component', async () => {
        render(Popup, {
          global: { plugins: [createTestingPinia()] }
        })
        const store = popup()
        await store.$patch({ popupData: 'new name' })
        screen.debug()
      })
    })
    

    或者您可以使用以下方案设置 initialState:

    import { render, screen } from '@testing-library/vue'
    import { createTestingPinia } from '@pinia/testing'
    import { popup } from '@/store1/popup/index'
    import Popup from '../../components/Popup/index.vue'
    
      test('displays popup with no inner component', async () => {
        const { getByTestId } = render(Popup, {
          global: {
            plugins: [
              createTestingPinia({
                initialState: {
                  popup: {
                    popupData: 'new name'
                  }
                }
              })
            ]
          }
        })
        const store = popup()
        screen.debug()
      })
    

    在哪里弹出in initialState - 是从 @/store1/popup 导入的 pinia 商店。您可以以相同的方式在那里指定其中的任何一个。

    Popup.vue

    <script>
    import { defineAsyncComponent, markRaw } from 'vue'
    import { mapState, mapActions } from 'pinia'
    import { popup } from '@/store1/popup/index'
    
    export default {
      data () {
        return {}
      },
      computed: {
        ...mapState(popup, ['popupData'])
      },
    ....
    

    【讨论】:

    • 请不要发布文字图片,发布文字本身
    【解决方案3】:

    我正在使用带有组合 API 样式的 Vue 3 开发一个项目。

    组合 API 用于组件和定义我的商店。

    播放器.js

    import { defineStore } from 'pinia'
    import { ref, reactive } from 'vue'
    
    export const usePlayerStore = defineStore('player',()=>{
        const isMainBtnGameClicked = ref(false)
    
        return { isMainBtnGameClicked }
    })
    

    我的组件.vue

    //import { usePlayerStore } from '...'
    const playerStore = usePlayerStore()        
    playerStore.isMainBtnGameClicked = true
    

    我的商店中的 isMainBtnGameClicked 已正确更新

    【讨论】:

      猜你喜欢
      • 2022-11-10
      • 2023-01-20
      • 2022-06-10
      • 1970-01-01
      • 2023-01-03
      • 2022-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多