web-dev-qa-db-ja.com

VueXから計算されたプロパティを監視するVueウォッチャーをテストする方法は?

次のコンポーネントがあるとします。

_import { mapState } from 'vuex';
import externalDependency from '...';

export default {
  name: 'Foo',
  computed: {
    ...mapState(['bar'])
  },
  watch: {
    bar () {
     externalDependency.doThing(this.bar);
    }
  }
}
_

テストするとき、次のようにexternalDependency.doThing()bar(vuex状態から取得)で呼び出されることを確認したいと思います。

_it('should call externalDependency.doThing with bar', () => {
  const wrapper = mount(Foo);
  const spy = jest.spyOn(externalDependency, 'doThing');

  wrapper.setComputed({bar: 'baz'});

  expect(spy).toHaveBeenCalledWith('baz');
});
_

Vue test-utilsには現在テストできるsetComputedメソッドがありますが、setComputedがまもなく削除されるという警告が表示され続け、他にどのようにテストできるかわかりません。

https://github.com/vuejs/vue-test-utils/issues/331

16
yxu296

Vue Test Utils ドキュメントは、非常に単純なVuexストアを使用する別のアプローチを示しています。

import { shallowMount, createLocalVue } from '@vue/test-utils'
import Vuex from 'vuex'

// use a localVue to prevent vuex state from polluting the global Vue instance
const localVue = createLocalVue();
localVue.use(Vuex);

describe('Foo.vue', () => {
  let state;
  let store;

  beforeEach(() => {
    // create a new store for each test to prevent pollution
    state = { bar: 'bar' };
    store = new Vuex.Store({ state });
  })

  it('should call externalDependency.doThing with bar', () => 
  {
    shallowMount(MyComponent, { store, localVue });
    const spy = jest.spyOn(externalDependency, 'doThing');
    // trigger the watch
    state.bar = 'baz';
    expect(spy).toHaveBeenCalledWith('baz');
  });
})
2
flup

ソース、つまりVueXで値を直接設定できます。だからあなたはあなたのstore.jsにこのようなものを持っているでしょう:

_const state = {
  bar: 'foo',
};
const mutations = {
  SET_BAR: (currentState, payload) => {
    currentState.bar = payload;
  },
};
const actions = {
  setBar: ({ commit }, payload) => {
    commit('SET_BAR', payload);
  },
};

export const mainStore = {
  state,
  mutations,
  actions,
};

export default new Vuex.Store(mainStore);
_

そしてあなたのcomponent.spec.jsであなたはこれをするでしょう:

_import { mainStore } from '../store';
import Vuex from 'vuex';

//... describe, and other setup functions
it('should call externalDependency.doThing with bar', async () => {
  const localState = {
    bar: 'foo',
  };
  const localStore = new Vuex.Store({
      ...mainStore,
      state: localState,
  });
  const wrapper = mount(Foo, {
    store: localStore,
  });
  const spy = jest.spyOn(externalDependency, 'doThing');
  localStore.state.bar = 'baz';
  await wrapper.vm.$nextTick();
  expect(spy).toHaveBeenCalledWith('baz');
});
_

ストアでdispatch('setBar', 'baz')メソッドを呼び出して、状態を直接設定する代わりに、ミューテーションを適切に発生させることもできます。

[〜#〜] nb [〜#〜]マウントごとに状態を再初期化することが重要です(つまり、クローンを作成するか、再宣言します)。そうしないと、ラッパーが破棄された場合でも、1つのテストで状態が変更され、次のテストはそのダーティ状態で開始されます。

1
ierdna

VueXインスタンスにはある種のミューテーターが必要になります。そうです、これはテストに別の無関係なユニットを導入しますが、個人的にはVuexの使用を含むテストによって、その概念はすでに破られています。

予期しない方法で状態を変更すると、実際の使用法とは異なる動作が発生する可能性が高くなります。

0
rosscooper